//----------------------------------------------
// NGUI: Next-Gen UI kit
// Copyright © 2011-2015 Tasharen Entertainment
//----------------------------------------------
using UnityEngine;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
///
/// Helper class containing generic functions used throughout the UI library.
///
static public class NGUITools
{
static AudioListener mListener;
static bool mLoaded = false;
static float mGlobalVolume = 1f;
///
/// Globally accessible volume affecting all sounds played via NGUITools.PlaySound().
///
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);
}
}
}
///
/// Helper function -- whether the disk access is allowed.
///
static public bool fileAccess
{
get
{
return true;
}
}
///
/// Play the specified audio clip.
///
static public AudioSource PlaySound (AudioClip clip) { return PlaySound(clip, 1f, 1f); }
///
/// Play the specified audio clip with the specified volume.
///
static public AudioSource PlaySound (AudioClip clip, float volume) { return PlaySound(clip, volume, 1f); }
static float mLastTimestamp = 0f;
static AudioClip mLastClip;
///
/// Play the specified audio clip with the specified volume and pitch.
///
static public AudioSource PlaySound (AudioClip clip, float volume, float pitch)
{
float time = RealTime.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();
}
}
if (mListener != null && mListener.enabled && NGUITools.GetActive(mListener.gameObject))
{
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7
AudioSource source = mListener.audio;
#else
AudioSource source = mListener.GetComponent();
#endif
if (source == null) source = mListener.gameObject.AddComponent();
#if !UNITY_FLASH
source.priority = 50;
source.pitch = pitch;
#endif
source.PlayOneShot(clip, volume);
return source;
}
}
return null;
}
///
/// 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.
///
// 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
// }
// ///
// /// 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.
// ///
// 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 : ""); }
// return www;
//#endif
// }
///
/// 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.
///
static public int RandomRange (int min, int max)
{
if (min == max) return min;
return UnityEngine.Random.Range(min, max + 1);
}
///
/// Returns the hierarchy of the object in a human-readable format.
///
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;
}
///
/// Find all active objects of specified type.
///
static public T[] FindActive () where T : Component
{
return GameObject.FindObjectsOfType(typeof(T)) as T[];
}
///
/// Find the camera responsible for drawing the objects on the specified layer.
///
static public Camera FindCameraForLayer (int layer,UIRoot root = null)
{
int layerMask = 1 << layer;
Camera cam;
if (root != null)
{
for (int i = 0; i < UICamera.list.size; ++i)
{
var uicam = UICamera.list.buffer[i];
cam = uicam.cachedCamera;
if (cam && root == uicam.Root && (cam.cullingMask & layerMask) != 0)
return 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();
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;
}
///
/// Add a collider to the game object containing one or more widgets.
///
static public void AddWidgetCollider (GameObject go) { AddWidgetCollider(go, false); }
///
/// Add a collider to the game object containing one or more widgets.
///
static public void AddWidgetCollider (GameObject go, bool considerInactive)
{
if (go != null)
{
// 3D collider
Collider col = go.GetComponent();
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();
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();
box2.isTrigger = true;
#if UNITY_EDITOR
UnityEditor.Undo.RegisterCreatedObjectUndo(box2, "Add Collider");
#endif
UIWidget widget = go.GetComponent();
if (widget != null) widget.autoResizeBoxCollider = true;
UpdateWidgetCollider(box2, considerInactive);
return;
}
else
{
box = go.AddComponent();
#if UNITY_EDITOR
UnityEditor.Undo.RegisterCreatedObjectUndo(box, "Add Collider");
#endif
box.isTrigger = true;
UIWidget widget = go.GetComponent();
if (widget != null) widget.autoResizeBoxCollider = true;
UpdateWidgetCollider(box, considerInactive);
}
}
return;
}
///
/// Adjust the widget's collider based on the depth of the widgets, as well as the widget's dimensions.
///
static public void UpdateWidgetCollider (GameObject go)
{
UpdateWidgetCollider(go, false);
}
///
/// Adjust the widget's collider based on the depth of the widgets, as well as the widget's dimensions.
///
static public void UpdateWidgetCollider (GameObject go, bool considerInactive)
{
if (go != null)
{
BoxCollider bc = go.GetComponent();
if (bc != null)
{
UpdateWidgetCollider(bc, considerInactive);
return;
}
BoxCollider2D box2 = go.GetComponent();
if (box2 != null) UpdateWidgetCollider(box2, considerInactive);
}
}
///
/// Adjust the widget's collider based on the depth of the widgets, as well as the widget's dimensions.
///
static public void UpdateWidgetCollider (BoxCollider box, bool considerInactive)
{
if (box != null)
{
GameObject go = box.gameObject;
UIWidget w = go.GetComponent();
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
}
}
///
/// Adjust the widget's collider based on the depth of the widgets, as well as the widget's dimensions.
///
static public void UpdateWidgetCollider (BoxCollider2D box, bool considerInactive)
{
if (box != null)
{
GameObject go = box.gameObject;
UIWidget w = go.GetComponent();
if (w != null)
{
Vector3[] corners = w.localCorners;
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7
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 || UNITY_4_7
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
}
}
///
/// Helper function that returns the string name of the type.
///
static public string GetTypeName ()
{
string s = typeof(T).ToString();
if (s.StartsWith("UI")) s = s.Substring(2);
else if (s.StartsWith("UnityEngine.")) s = s.Substring(12);
return s;
}
///
/// Helper function that returns the string name of the type.
///
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;
}
///
/// Convenience method that works without warnings in both Unity 3 and 4.
///
static public void RegisterUndo (UnityEngine.Object obj, string name)
{
#if UNITY_EDITOR
UnityEditor.Undo.RecordObject(obj, name);
NGUITools.SetDirty(obj);
#endif
}
///
/// Convenience function that marks the specified object as dirty in the Unity Editor.
///
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
}
///
/// Add a new child game object.
///
static public GameObject AddChild (GameObject parent) { return AddChild(parent, true); }
///
/// Add a new child game object.
///
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;
}
///
/// Instantiate an object and add it to the specified parent.
///
///
//设置按钮以下全部置灰并且不能点击
static public void SetButtonGrayAndNotOnClick( Transform trs, bool isgray ) {
if (trs == null)
{
return;
}
var spr = trs.GetComponent();
if (spr != null)
{
spr.IsGray = isgray;
}
var box = trs.GetComponent();
if (box != null)
{
box.enabled = !isgray;
}
for (int i = 0; i < trs.childCount;++i)
{
var _trs = trs.GetChild(i);
SetButtonGrayAndNotOnClick(_trs, isgray);
}
}
//克隆物体,count是长度,可复用
static public List AddChilds(GameObject parent,GameObject prefab, int count)
{
List objlist = new List(count);
int allcount = parent.transform.childCount;
for (int i = 0; i < count; ++i)
{
if (i < allcount)
{
parent.transform.GetChild(i).gameObject.SetActive(true);
objlist.Add(parent.transform.GetChild(i).gameObject);
}
else
{
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;
go.SetActive(true);
}
objlist.Add(go);
}
}
allcount = parent.transform.childCount;
for (int i = count; i < allcount; ++i)
{
parent.transform.GetChild(i).gameObject.SetActive(false);
}
return objlist;
}
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;
}
///
/// Calculate the game object's depth based on the widgets within, and also taking panel depth into consideration.
///
static public int CalculateRaycastDepth (GameObject go)
{
UIWidget w = go.GetComponent();
if (w != null) return w.raycastDepth;
UIWidget[] widgets = go.GetComponentsInChildren();
if (widgets.Length == 0) return int.MinValue;
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;
}
///
/// Gathers all widgets and calculates the depth for the next widget.
///
static public int CalculateNextDepth (GameObject go)
{
if (go)
{
int depth = -1;
UIWidget[] widgets = go.GetComponentsInChildren();
for (int i = 0, imax = widgets.Length; i < imax; ++i)
depth = Mathf.Max(depth, widgets[i].depth);
return depth + 1;
}
return 0;
}
///
/// Gathers all widgets and calculates the depth for the next widget.
///
static public int CalculateNextDepth (GameObject go, bool ignoreChildrenWithColliders)
{
if (go && ignoreChildrenWithColliders)
{
int depth = -1;
UIWidget[] widgets = go.GetComponentsInChildren();
for (int i = 0, imax = widgets.Length; i < imax; ++i)
{
UIWidget w = widgets[i];
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7
if (w.cachedGameObject != go && (w.collider != null || w.GetComponent() != null)) continue;
#else
if (w.cachedGameObject != go && (w.GetComponent() != null || w.GetComponent() != null)) continue;
#endif
depth = Mathf.Max(depth, w.depth);
}
return depth + 1;
}
return CalculateNextDepth(go);
}
///
/// 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.
///
///
static public int AdjustDepth (GameObject go, int adjustment)
{
if (go != null)
{
UIPanel panel = go.GetComponent();
if (panel != null)
{
UIPanel[] panels = go.GetComponentsInChildren(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(go);
if (panel == null) return 0;
UIWidget[] widgets = go.GetComponentsInChildren(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;
}
///
/// Bring all of the widgets on the specified object forward.
///
static public void BringForward (GameObject go)
{
int val = AdjustDepth(go, 1000);
if (val == 1) NormalizePanelDepths();
else if (val == 2) NormalizeWidgetDepths();
}
///
/// Push all of the widgets on the specified object back, making them appear behind everything else.
///
static public void PushBack (GameObject go)
{
int val = AdjustDepth(go, -1000);
if (val == 1) NormalizePanelDepths();
else if (val == 2) NormalizeWidgetDepths();
}
///
/// Normalize the depths of all the widgets and panels in the scene, making them start from 0 and remain in order.
///
static public void NormalizeDepths ()
{
NormalizeWidgetDepths();
NormalizePanelDepths();
}
///
/// Normalize the depths of all the widgets in the scene, making them start from 0 and remain in order.
///
static public void NormalizeWidgetDepths ()
{
NormalizeWidgetDepths(FindActive());
}
///
/// Normalize the depths of all the widgets in the scene, making them start from 0 and remain in order.
///
static public void NormalizeWidgetDepths (GameObject go)
{
NormalizeWidgetDepths(go.GetComponentsInChildren());
}
///
/// Normalize the depths of all the widgets in the scene, making them start from 0 and remain in order.
///
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;
}
}
}
}
///
/// Normalize the depths of all the panels in the scene, making them start from 0 and remain in order.
///
static public void NormalizePanelDepths ()
{
UIPanel[] list = FindActive();
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;
}
}
}
}
///
/// Create a new UI.
///
static public UIPanel CreateUI (bool advanced3D) { return CreateUI(null, advanced3D, -1); }
///
/// Create a new UI.
///
static public UIPanel CreateUI (bool advanced3D, int layer) { return CreateUI(null, advanced3D, layer); }
///
/// Create a new UI.
///
static public UIPanel CreateUI (Transform trans, bool advanced3D, int layer)
{
// Find the existing UI Root
UIRoot root = (trans != null) ? NGUITools.FindInParents(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();
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7
if (cam != null && cam.camera.isOrthoGraphic == advanced3D)
#else
if (cam != null && cam.GetComponent().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();
// 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();
if (panel == null)
{
// Find other active cameras in the scene
Camera[] cameras = NGUITools.FindActive();
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(root.gameObject, false);
cam.gameObject.AddComponent();
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();
if (listeners == null || listeners.Length == 0)
cam.gameObject.AddComponent();
// Add a panel to the root
panel = root.gameObject.AddComponent();
#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();
}
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;
}
///
/// Helper function that recursively sets all children with widgets' game objects layers to the specified value.
///
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);
}
}
///
/// Add a child object to the specified parent and attaches the specified script to it.
///
static public T AddChild (GameObject parent) where T : Component
{
GameObject go = AddChild(parent);
go.name = GetTypeName();
return go.AddComponent();
}
///
/// Add a child object to the specified parent and attaches the specified script to it.
///
static public T AddChild (GameObject parent, bool undo) where T : Component
{
GameObject go = AddChild(parent, undo);
go.name = GetTypeName();
return go.AddComponent();
}
///
/// Add a new widget of specified type.
///
static public T AddWidget (GameObject go, int depth = int.MaxValue) where T : UIWidget
{
if (depth == int.MaxValue) depth = CalculateNextDepth(go);
// Create the widget and place it above other widgets
T widget = AddChild(go);
widget.width = 100;
widget.height = 100;
widget.depth = depth;
return widget;
}
///
/// 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.
///
static public UISprite AddSprite (GameObject go, UIAtlas atlas, string spriteName, int depth = int.MaxValue)
{
UISpriteData sp = (atlas != null) ? atlas.GetSprite(spriteName) : null;
UISprite sprite = AddWidget(go, depth);
sprite.type = (sp == null || !sp.hasBorder) ? UISprite.Type.Simple : UISprite.Type.Sliced;
sprite.atlas = atlas;
sprite.spriteName = spriteName;
return sprite;
}
///
/// Get the rootmost object of the specified game object.
///
static public GameObject GetRoot (GameObject go)
{
Transform t = go.transform;
for (; ; )
{
Transform parent = t.parent;
if (parent == null) break;
t = parent;
}
return t.gameObject;
}
///
/// Finds the specified component on the game object or one of its parents.
///
static public T FindInParents (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();
#else
T comp = go.GetComponent();
#endif
if (comp == null)
{
Transform t = go.transform.parent;
while (t != null && comp == null)
{
comp = t.gameObject.GetComponent();
t = t.parent;
}
}
#if UNITY_FLASH
return (T)comp;
#else
return comp;
#endif
//#else
// return go.GetComponentInParent();
//#endif
}
///
/// Finds the specified component on the game object or one of its parents.
///
static public T FindInParents (Transform trans) where T : Component
{
if (trans == null) return null;
#if UNITY_4_3
#if UNITY_FLASH
object comp = trans.GetComponent();
#else
T comp = trans.GetComponent();
#endif
if (comp == null)
{
Transform t = trans.transform.parent;
while (t != null && comp == null)
{
comp = t.gameObject.GetComponent();
t = t.parent;
}
}
#if UNITY_FLASH
return (T)comp;
#else
return comp;
#endif
#else
return trans.GetComponentInParent();
#endif
}
///
/// Destroy the specified object, immediately if in edit mode.
///
static public void Destroy (UnityEngine.Object obj)
{
if (obj)
{
if (obj is Transform)
{
Transform t = (obj as Transform);
GameObject go = t.gameObject;
if (Application.isPlaying)
{
t.parent = null;
UnityEngine.Object.Destroy(go);
}
else UnityEngine.Object.DestroyImmediate(go);
}
else if (obj is GameObject)
{
GameObject go = obj as GameObject;
Transform t = go.transform;
if (Application.isPlaying)
{
t.parent = null;
UnityEngine.Object.Destroy(go);
}
else UnityEngine.Object.DestroyImmediate(go);
}
else if (Application.isPlaying) UnityEngine.Object.Destroy(obj);
else UnityEngine.Object.DestroyImmediate(obj);
}
}
///
/// Convenience extension that destroys all children of the transform.
///
static public void DestroyChildren (this Transform t)
{
bool isPlaying = Application.isPlaying;
while (t.childCount != 0)
{
Transform child = t.GetChild(0);
if (isPlaying)
{
child.parent = null;
UnityEngine.Object.Destroy(child.gameObject);
}
else UnityEngine.Object.DestroyImmediate(child.gameObject);
}
}
///
/// Destroy the specified object immediately, unless not in the editor, in which case the regular Destroy is used instead.
///
static public void DestroyImmediate (UnityEngine.Object obj)
{
if (obj != null)
{
if (Application.isEditor) UnityEngine.Object.DestroyImmediate(obj);
else UnityEngine.Object.Destroy(obj);
}
}
///
/// Call the specified function on all objects in the scene.
///
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);
}
///
/// Call the specified function on all objects in the scene.
///
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);
}
///
/// Determines whether the 'parent' contains a 'child' in its hierarchy.
///
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;
}
///
/// Activate the specified object and all of its children.
///
static void Activate (Transform t) { Activate(t, false); }
///
/// Activate the specified object and all of its children.
///
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);
}
}
}
///
/// Deactivate the specified object and all of its children.
///
static void Deactivate (Transform t) { SetActiveSelf(t.gameObject, false); }
///
/// 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.
///
static public void SetActive (GameObject go, bool state) { SetActive(go, state, true); }
///
/// 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.
///
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);
}
}
///
/// Ensure that all widgets have had their panels created, forcing the update right away rather than on the following frame.
///
[System.Diagnostics.DebuggerHidden]
[System.Diagnostics.DebuggerStepThrough]
static void CallCreatePanel (Transform t)
{
UIWidget w = t.GetComponent();
if (w != null) w.CreatePanel();
for (int i = 0, imax = t.childCount; i < imax; ++i)
CallCreatePanel(t.GetChild(i));
}
///
/// Activate or deactivate children of the specified game object without changing the active state of the object itself.
///
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);
}
}
}
///
/// Helper function that returns whether the specified MonoBehaviour is active.
///
[System.Obsolete("Use NGUITools.GetActive instead")]
static public bool IsActive (Behaviour mb)
{
return mb != null && mb.enabled && mb.gameObject.activeInHierarchy;
}
///
/// Helper function that returns whether the specified MonoBehaviour is active.
///
[System.Diagnostics.DebuggerHidden]
[System.Diagnostics.DebuggerStepThrough]
static public bool GetActive (Behaviour mb)
{
return mb && mb.enabled && mb.gameObject.activeInHierarchy;
}
///
/// Unity4 has changed GameObject.active to GameObject.activeself.
///
[System.Diagnostics.DebuggerHidden]
[System.Diagnostics.DebuggerStepThrough]
static public bool GetActive (GameObject go)
{
return go && go.activeInHierarchy;
}
///
/// Unity4 has changed GameObject.active to GameObject.SetActive.
///
[System.Diagnostics.DebuggerHidden]
[System.Diagnostics.DebuggerStepThrough]
static public void SetActiveSelf (GameObject go, bool state)
{
go.SetActive(state);
}
///
/// Recursively set the game object's layer.
///
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);
}
}
///
/// Helper function used to make the vector use integer numbers.
///
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;
}
///
/// Make the specified selection pixel-perfect.
///
static public void MakePixelPerfect (Transform t)
{
UIWidget w = t.GetComponent();
if (w != null) w.MakePixelPerfect();
if (t.GetComponent() == null && t.GetComponent() == 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));
}
///
/// Save the specified binary data into the specified file.
///
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 = Application.persistentDataPath + "/" + fileName;
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
}
///
/// Load all binary data from the specified file.
///
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 = Application.persistentDataPath + "/" + fileName;
if (File.Exists(path))
{
return File.ReadAllBytes(path);
}
return null;
#endif
}
///
/// Pre-multiply shaders result in a black outline if this operation is done in the shader. It's better to do it outside.
///
static public Color ApplyPMA (Color c)
{
if (c.a != 1f)
{
c.r *= c.a;
c.g *= c.a;
c.b *= c.a;
}
return c;
}
///
/// Inform all widgets underneath the specified object that the parent has changed.
///
static public void MarkParentAsChanged (GameObject go)
{
UIRect[] rects = go.GetComponentsInChildren();
for (int i = 0, imax = rects.Length; i < imax; ++i)
rects[i].ParentHasChanged();
}
///
/// Access to the clipboard via undocumented APIs.
///
static public string clipboard
{
get
{
TextEditor te = new TextEditor();
te.Paste();
return te.text;
}
set
{
TextEditor te = new TextEditor();
te.text = new GUIContent(value).text;
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); }
///
/// 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.
///
static public T AddMissingComponent (this GameObject go) where T : Component
{
#if UNITY_FLASH
object comp = go.GetComponent();
#else
T comp = go.GetComponent();
#endif
if (comp == null)
{
#if UNITY_EDITOR
if (!Application.isPlaying)
RegisterUndo(go, "Add " + typeof(T));
#endif
comp = go.AddComponent();
}
#if UNITY_FLASH
return (T)comp;
#else
return comp;
#endif
}
// Temporary variable to avoid GC allocation
static Vector3[] mSides = new Vector3[4];
///
/// Get sides relative to the specified camera. The order is left, top, right, bottom.
///
static public Vector3[] GetSides (this Camera cam)
{
return cam.GetSides(Mathf.Lerp(cam.nearClipPlane, cam.farClipPlane, 0.5f), null);
}
///
/// Get sides relative to the specified camera. The order is left, top, right, bottom.
///
static public Vector3[] GetSides (this Camera cam, float depth)
{
return cam.GetSides(depth, null);
}
///
/// Get sides relative to the specified camera. The order is left, top, right, bottom.
///
static public Vector3[] GetSides (this Camera cam, Transform relativeTo)
{
return cam.GetSides(Mathf.Lerp(cam.nearClipPlane, cam.farClipPlane, 0.5f), relativeTo);
}
///
/// Get sides relative to the specified camera. The order is left, top, right, bottom.
///
static public Vector3[] GetSides (this Camera cam, float depth, Transform relativeTo)
{
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7
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;
}
///
/// Get the camera's world-space corners. The order is bottom-left, top-left, top-right, bottom-right.
///
static public Vector3[] GetWorldCorners (this Camera cam)
{
float depth = Mathf.Lerp(cam.nearClipPlane, cam.farClipPlane, 0.5f);
return cam.GetWorldCorners(depth, null);
}
///
/// Get the camera's world-space corners. The order is bottom-left, top-left, top-right, bottom-right.
///
static public Vector3[] GetWorldCorners (this Camera cam, float depth)
{
return cam.GetWorldCorners(depth, null);
}
///
/// Get the camera's world-space corners. The order is bottom-left, top-left, top-right, bottom-right.
///
static public Vector3[] GetWorldCorners (this Camera cam, Transform relativeTo)
{
return cam.GetWorldCorners(Mathf.Lerp(cam.nearClipPlane, cam.farClipPlane, 0.5f), relativeTo);
}
///
/// Get the camera's world-space corners. The order is bottom-left, top-left, top-right, bottom-right.
///
static public Vector3[] GetWorldCorners (this Camera cam, float depth, Transform relativeTo)
{
#if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7
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;
}
///
/// Convenience function that converts Class + Function combo into Class.Function representation.
///
static public string GetFuncName (object obj, string method)
{
if (obj == null) return "";
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
///
/// Execute the specified function on the target game object.
///
static public void Execute (GameObject go, string funcName) where T : Component
{
T[] comps = go.GetComponents();
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
}
}
///
/// Execute the specified function on the target game object and all of its children.
///
static public void ExecuteAll (GameObject root, string funcName) where T : Component
{
Execute(root, funcName);
Transform t = root.transform;
for (int i = 0, imax = t.childCount; i < imax; ++i)
ExecuteAll(t.GetChild(i).gameObject, funcName);
}
///
/// 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.
///
static public void ImmediatelyCreateDrawCalls (GameObject root)
{
ExecuteAll(root, "Start");
ExecuteAll(root, "Start");
ExecuteAll(root, "Update");
ExecuteAll(root, "Update");
ExecuteAll(root, "LateUpdate");
}
#endif
#if UNITY_EDITOR
static int mSizeFrame = -1;
static System.Reflection.MethodInfo s_GetSizeOfMainGameView;
static Vector2 mGameSize = Vector2.one;
///
/// Size of the game view cannot be retrieved from Screen.width and Screen.height when the game view is hidden.
///
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
///
/// Size of the game view cannot be retrieved from Screen.width and Screen.height when the game view is hidden.
///
static public Vector2 screenSize { get { return new Vector2(Screen.width, Screen.height); } }
#endif
///
/// List of keys that can be checked.
///
static public KeyCode[] keys = new KeyCode[]
{
KeyCode.Backspace, // 8,
KeyCode.Tab, // 9,
KeyCode.Clear, // 12,
KeyCode.Return, // 13,
KeyCode.Pause, // 19,
KeyCode.Escape, // 27,
KeyCode.Space, // 32,
KeyCode.Exclaim, // 33,
KeyCode.DoubleQuote, // 34,
KeyCode.Hash, // 35,
KeyCode.Dollar, // 36,
KeyCode.Ampersand, // 38,
KeyCode.Quote, // 39,
KeyCode.LeftParen, // 40,
KeyCode.RightParen, // 41,
KeyCode.Asterisk, // 42,
KeyCode.Plus, // 43,
KeyCode.Comma, // 44,
KeyCode.Minus, // 45,
KeyCode.Period, // 46,
KeyCode.Slash, // 47,
KeyCode.Alpha0, // 48,
KeyCode.Alpha1, // 49,
KeyCode.Alpha2, // 50,
KeyCode.Alpha3, // 51,
KeyCode.Alpha4, // 52,
KeyCode.Alpha5, // 53,
KeyCode.Alpha6, // 54,
KeyCode.Alpha7, // 55,
KeyCode.Alpha8, // 56,
KeyCode.Alpha9, // 57,
KeyCode.Colon, // 58,
KeyCode.Semicolon, // 59,
KeyCode.Less, // 60,
KeyCode.Equals, // 61,
KeyCode.Greater, // 62,
KeyCode.Question, // 63,
KeyCode.At, // 64,
KeyCode.LeftBracket, // 91,
KeyCode.Backslash, // 92,
KeyCode.RightBracket, // 93,
KeyCode.Caret, // 94,
KeyCode.Underscore, // 95,
KeyCode.BackQuote, // 96,
KeyCode.A, // 97,
KeyCode.B, // 98,
KeyCode.C, // 99,
KeyCode.D, // 100,
KeyCode.E, // 101,
KeyCode.F, // 102,
KeyCode.G, // 103,
KeyCode.H, // 104,
KeyCode.I, // 105,
KeyCode.J, // 106,
KeyCode.K, // 107,
KeyCode.L, // 108,
KeyCode.M, // 109,
KeyCode.N, // 110,
KeyCode.O, // 111,
KeyCode.P, // 112,
KeyCode.Q, // 113,
KeyCode.R, // 114,
KeyCode.S, // 115,
KeyCode.T, // 116,
KeyCode.U, // 117,
KeyCode.V, // 118,
KeyCode.W, // 119,
KeyCode.X, // 120,
KeyCode.Y, // 121,
KeyCode.Z, // 122,
KeyCode.Delete, // 127,
KeyCode.Keypad0, // 256,
KeyCode.Keypad1, // 257,
KeyCode.Keypad2, // 258,
KeyCode.Keypad3, // 259,
KeyCode.Keypad4, // 260,
KeyCode.Keypad5, // 261,
KeyCode.Keypad6, // 262,
KeyCode.Keypad7, // 263,
KeyCode.Keypad8, // 264,
KeyCode.Keypad9, // 265,
KeyCode.KeypadPeriod, // 266,
KeyCode.KeypadDivide, // 267,
KeyCode.KeypadMultiply, // 268,
KeyCode.KeypadMinus, // 269,
KeyCode.KeypadPlus, // 270,
KeyCode.KeypadEnter, // 271,
KeyCode.KeypadEquals, // 272,
KeyCode.UpArrow, // 273,
KeyCode.DownArrow, // 274,
KeyCode.RightArrow, // 275,
KeyCode.LeftArrow, // 276,
KeyCode.Insert, // 277,
KeyCode.Home, // 278,
KeyCode.End, // 279,
KeyCode.PageUp, // 280,
KeyCode.PageDown, // 281,
KeyCode.F1, // 282,
KeyCode.F2, // 283,
KeyCode.F3, // 284,
KeyCode.F4, // 285,
KeyCode.F5, // 286,
KeyCode.F6, // 287,
KeyCode.F7, // 288,
KeyCode.F8, // 289,
KeyCode.F9, // 290,
KeyCode.F10, // 291,
KeyCode.F11, // 292,
KeyCode.F12, // 293,
KeyCode.F13, // 294,
KeyCode.F14, // 295,
KeyCode.F15, // 296,
KeyCode.Numlock, // 300,
KeyCode.CapsLock, // 301,
KeyCode.ScrollLock, // 302,
KeyCode.RightShift, // 303,
KeyCode.LeftShift, // 304,
KeyCode.RightControl, // 305,
KeyCode.LeftControl, // 306,
KeyCode.RightAlt, // 307,
KeyCode.LeftAlt, // 308,
//KeyCode.Mouse0, // 323,
//KeyCode.Mouse1, // 324,
//KeyCode.Mouse2, // 325,
KeyCode.Mouse3, // 326,
KeyCode.Mouse4, // 327,
KeyCode.Mouse5, // 328,
KeyCode.Mouse6, // 329,
KeyCode.JoystickButton0, // 330,
KeyCode.JoystickButton1, // 331,
KeyCode.JoystickButton2, // 332,
KeyCode.JoystickButton3, // 333,
KeyCode.JoystickButton4, // 334,
KeyCode.JoystickButton5, // 335,
KeyCode.JoystickButton6, // 336,
KeyCode.JoystickButton7, // 337,
KeyCode.JoystickButton8, // 338,
KeyCode.JoystickButton9, // 339,
KeyCode.JoystickButton10, // 340,
KeyCode.JoystickButton11, // 341,
KeyCode.JoystickButton12, // 342,
KeyCode.JoystickButton13, // 343,
KeyCode.JoystickButton14, // 344,
KeyCode.JoystickButton15, // 345,
KeyCode.JoystickButton16, // 346,
KeyCode.JoystickButton17, // 347,
KeyCode.JoystickButton18, // 348,
KeyCode.JoystickButton19, // 349,
};
///
/// Helper function that converts the specified key to a 3-character key identifier for captions.
///
static public string KeyToCaption (KeyCode key)
{
switch (key)
{
case KeyCode.None: return null;
case KeyCode.Backspace: return "BS";
case KeyCode.Tab: return "Tab";
case KeyCode.Clear: return "Clr";
case KeyCode.Return: return "NT";
case KeyCode.Pause: return "PS";
case KeyCode.Escape: return "Esc";
case KeyCode.Space: return "SP";
case KeyCode.Exclaim: return "!";
case KeyCode.DoubleQuote: return "\"";
case KeyCode.Hash: return "#";
case KeyCode.Dollar: return "$";
case KeyCode.Ampersand: return "&";
case KeyCode.Quote: return "'";
case KeyCode.LeftParen: return "(";
case KeyCode.RightParen: return ")";
case KeyCode.Asterisk: return "*";
case KeyCode.Plus: return "+";
case KeyCode.Comma: return ",";
case KeyCode.Minus: return "-";
case KeyCode.Period: return ".";
case KeyCode.Slash: return "/";
case KeyCode.Alpha0: return "0";
case KeyCode.Alpha1: return "1";
case KeyCode.Alpha2: return "2";
case KeyCode.Alpha3: return "3";
case KeyCode.Alpha4: return "4";
case KeyCode.Alpha5: return "5";
case KeyCode.Alpha6: return "6";
case KeyCode.Alpha7: return "7";
case KeyCode.Alpha8: return "8";
case KeyCode.Alpha9: return "9";
case KeyCode.Colon: return ":";
case KeyCode.Semicolon: return ";";
case KeyCode.Less: return "<";
case KeyCode.Equals: return "=";
case KeyCode.Greater: return ">";
case KeyCode.Question: return "?";
case KeyCode.At: return "@";
case KeyCode.LeftBracket: return "[";
case KeyCode.Backslash: return "\\";
case KeyCode.RightBracket: return "]";
case KeyCode.Caret: return "^";
case KeyCode.Underscore: return "_";
case KeyCode.BackQuote: return "`";
case KeyCode.A: return "A";
case KeyCode.B: return "B";
case KeyCode.C: return "C";
case KeyCode.D: return "D";
case KeyCode.E: return "E";
case KeyCode.F: return "F";
case KeyCode.G: return "G";
case KeyCode.H: return "H";
case KeyCode.I: return "I";
case KeyCode.J: return "J";
case KeyCode.K: return "K";
case KeyCode.L: return "L";
case KeyCode.M: return "M";
case KeyCode.N: return "N0";
case KeyCode.O: return "O";
case KeyCode.P: return "P";
case KeyCode.Q: return "Q";
case KeyCode.R: return "R";
case KeyCode.S: return "S";
case KeyCode.T: return "T";
case KeyCode.U: return "U";
case KeyCode.V: return "V";
case KeyCode.W: return "W";
case KeyCode.X: return "X";
case KeyCode.Y: return "Y";
case KeyCode.Z: return "Z";
case KeyCode.Delete: return "Del";
case KeyCode.Keypad0: return "K0";
case KeyCode.Keypad1: return "K1";
case KeyCode.Keypad2: return "K2";
case KeyCode.Keypad3: return "K3";
case KeyCode.Keypad4: return "K4";
case KeyCode.Keypad5: return "K5";
case KeyCode.Keypad6: return "K6";
case KeyCode.Keypad7: return "K7";
case KeyCode.Keypad8: return "K8";
case KeyCode.Keypad9: return "K9";
case KeyCode.KeypadPeriod: return ".";
case KeyCode.KeypadDivide: return "/";
case KeyCode.KeypadMultiply: return "*";
case KeyCode.KeypadMinus: return "-";
case KeyCode.KeypadPlus: return "+";
case KeyCode.KeypadEnter: return "NT";
case KeyCode.KeypadEquals: return "=";
case KeyCode.UpArrow: return "UP";
case KeyCode.DownArrow: return "DN";
case KeyCode.RightArrow: return "LT";
case KeyCode.LeftArrow: return "RT";
case KeyCode.Insert: return "Ins";
case KeyCode.Home: return "Home";
case KeyCode.End: return "End";
case KeyCode.PageUp: return "PU";
case KeyCode.PageDown: return "PD";
case KeyCode.F1: return "F1";
case KeyCode.F2: return "F2";
case KeyCode.F3: return "F3";
case KeyCode.F4: return "F4";
case KeyCode.F5: return "F5";
case KeyCode.F6: return "F6";
case KeyCode.F7: return "F7";
case KeyCode.F8: return "F8";
case KeyCode.F9: return "F9";
case KeyCode.F10: return "F10";
case KeyCode.F11: return "F11";
case KeyCode.F12: return "F12";
case KeyCode.F13: return "F13";
case KeyCode.F14: return "F14";
case KeyCode.F15: return "F15";
case KeyCode.Numlock: return "Num";
case KeyCode.CapsLock: return "Cap";
case KeyCode.ScrollLock: return "Scr";
case KeyCode.RightShift: return "RS";
case KeyCode.LeftShift: return "LS";
case KeyCode.RightControl: return "RC";
case KeyCode.LeftControl: return "LC";
case KeyCode.RightAlt: return "RA";
case KeyCode.LeftAlt: return "LA";
case KeyCode.Mouse0: return "M0";
case KeyCode.Mouse1: return "M1";
case KeyCode.Mouse2: return "M2";
case KeyCode.Mouse3: return "M3";
case KeyCode.Mouse4: return "M4";
case KeyCode.Mouse5: return "M5";
case KeyCode.Mouse6: return "M6";
case KeyCode.JoystickButton0: return "(A)";
case KeyCode.JoystickButton1: return "(B)";
case KeyCode.JoystickButton2: return "(X)";
case KeyCode.JoystickButton3: return "(Y)";
case KeyCode.JoystickButton4: return "(RB)";
case KeyCode.JoystickButton5: return "(LB)";
case KeyCode.JoystickButton6: return "(Back)";
case KeyCode.JoystickButton7: return "(Start)";
case KeyCode.JoystickButton8: return "(LS)";
case KeyCode.JoystickButton9: return "(RS)";
case KeyCode.JoystickButton10: return "J10";
case KeyCode.JoystickButton11: return "J11";
case KeyCode.JoystickButton12: return "J12";
case KeyCode.JoystickButton13: return "J13";
case KeyCode.JoystickButton14: return "J14";
case KeyCode.JoystickButton15: return "J15";
case KeyCode.JoystickButton16: return "J16";
case KeyCode.JoystickButton17: return "J17";
case KeyCode.JoystickButton18: return "J18";
case KeyCode.JoystickButton19: return "J19";
}
return null;
}
//获取4顶点差值的颜色
static public Color GetVertsColor(Vector4 v, Vector3 pos, Color clt, Color clb, Color crt, Color crb)
{
var xLerp = (pos.x - v.x) / Mathf.Abs(v.x - v.z);
var yLerp = (pos.y - v.y) / Mathf.Abs(v.y - v.w);
var c1 = Color.Lerp(clb, clt, yLerp);
var c2 = Color.Lerp(crb, crt, yLerp);
return Color.Lerp(c1, c2, xLerp);
}
}