using System; using System.Collections; using System.Collections.Generic; using I2.Loc; using UnityEngine; [ExecuteInEditMode] [AddComponentMenu("NGUI/Interaction/Popup List")] public class UIPopupList : UIWidgetContainer { public UnityEngine.Object ambigiousFont { get { if (this.trueTypeFont != null) { return this.trueTypeFont; } if (this.bitmapFont != null) { return this.bitmapFont; } return this.font; } set { if (value is Font) { this.trueTypeFont = (value as Font); this.bitmapFont = null; this.font = null; } else if (value is UIFont) { this.bitmapFont = (value as UIFont); this.trueTypeFont = null; this.font = null; } } } [Obsolete("Use EventDelegate.Add(popup.onChange, YourCallback) instead, and UIPopupList.current.value to determine the state")] public UIPopupList.LegacyEvent onSelectionChange { get { return this.mLegacyEvent; } set { this.mLegacyEvent = value; } } public bool isOpen { get { return this.mChild != null; } } public string value { get { return this.mSelectedItem; } set { this.mSelectedItem = value; if (this.mSelectedItem == null) { return; } if (this.mSelectedItem != null) { this.TriggerCallbacks(); } } } public object data { get { int num = this.items.IndexOf(this.mSelectedItem); return (num <= -1 || num >= this.itemData.Count) ? null : this.itemData[num]; } } [Obsolete("Use 'value' instead")] public string selection { get { return this.value; } set { this.value = value; } } private bool handleEvents { get { UIKeyNavigation component = base.GetComponent(); return component == null || !component.enabled; } set { UIKeyNavigation component = base.GetComponent(); if (component != null) { component.enabled = !value; } } } private bool isValid { get { return this.bitmapFont != null || this.trueTypeFont != null; } } private int activeFontSize { get { return (!(this.trueTypeFont != null) && !(this.bitmapFont == null)) ? this.bitmapFont.defaultSize : this.fontSize; } } private float activeFontScale { get { return (!(this.trueTypeFont != null) && !(this.bitmapFont == null)) ? ((float)this.fontSize / (float)this.bitmapFont.defaultSize) : 1f; } } public void Clear() { this.items.Clear(); this.itemData.Clear(); } public void AddItem(string text) { this.items.Add(text); this.itemData.Add(null); } public void AddItem(string text, object data) { this.items.Add(text); this.itemData.Add(data); } protected void TriggerCallbacks() { if (UIPopupList.current != this) { UIPopupList uipopupList = UIPopupList.current; UIPopupList.current = this; if (this.mLegacyEvent != null) { this.mLegacyEvent(this.mSelectedItem); } if (EventDelegate.IsValid(this.onChange)) { EventDelegate.Execute(this.onChange); } else if (this.eventReceiver != null && !string.IsNullOrEmpty(this.functionName)) { this.eventReceiver.SendMessage(this.functionName, this.mSelectedItem, SendMessageOptions.DontRequireReceiver); } UIPopupList.current = uipopupList; } } private void OnEnable() { if (EventDelegate.IsValid(this.onChange)) { this.eventReceiver = null; this.functionName = null; } if (this.font != null) { if (this.font.isDynamic) { this.trueTypeFont = this.font.dynamicFont; this.fontStyle = this.font.dynamicFontStyle; this.mUseDynamicFont = true; } else if (this.bitmapFont == null) { this.bitmapFont = this.font; this.mUseDynamicFont = false; } this.font = null; } if (this.textScale != 0f) { this.fontSize = ((!(this.bitmapFont != null)) ? 16 : Mathf.RoundToInt((float)this.bitmapFont.defaultSize * this.textScale)); this.textScale = 0f; } if (this.trueTypeFont == null && this.bitmapFont != null && this.bitmapFont.isDynamic) { this.trueTypeFont = this.bitmapFont.dynamicFont; this.bitmapFont = null; } } private void OnValidate() { Font x = this.trueTypeFont; UIFont uifont = this.bitmapFont; this.bitmapFont = null; this.trueTypeFont = null; if (x != null && (uifont == null || !this.mUseDynamicFont)) { this.bitmapFont = null; this.trueTypeFont = x; this.mUseDynamicFont = true; } else if (uifont != null) { if (uifont.isDynamic) { this.trueTypeFont = uifont.dynamicFont; this.fontStyle = uifont.dynamicFontStyle; this.fontSize = uifont.defaultSize; this.mUseDynamicFont = true; } else { this.bitmapFont = uifont; this.mUseDynamicFont = false; } } else { this.trueTypeFont = x; this.mUseDynamicFont = true; } } private void Start() { if (this.textLabel != null) { EventDelegate.Add(this.onChange, new EventDelegate.Callback(this.textLabel.SetCurrentSelection)); this.textLabel = null; } if (Application.isPlaying) { if (string.IsNullOrEmpty(this.mSelectedItem)) { if (this.items.Count > 0) { this.value = this.items[0]; } } else { string value = this.mSelectedItem; this.mSelectedItem = null; this.value = value; } } } private void OnLocalize() { if (this.isLocalized) { this.TriggerCallbacks(); } } private void Highlight(UILabel lbl, bool instant) { if (this.mHighlight != null) { this.mHighlightedLabel = lbl; if (this.mHighlight.GetAtlasSprite() == null) { return; } Vector3 highlightPosition = this.GetHighlightPosition(); if (instant || !this.isAnimated) { this.mHighlight.cachedTransform.localPosition = highlightPosition; } else { TweenPosition.Begin(this.mHighlight.gameObject, 0.1f, highlightPosition).method = UITweener.Method.EaseOut; if (!this.mTweening) { this.mTweening = true; base.StartCoroutine("UpdateTweenPosition"); } } } } private Vector3 GetHighlightPosition() { if (this.mHighlightedLabel == null || this.mHighlight == null) { return Vector3.zero; } UISpriteData atlasSprite = this.mHighlight.GetAtlasSprite(); if (atlasSprite == null) { return Vector3.zero; } float pixelSize = this.atlas.pixelSize; float num = (float)atlasSprite.borderLeft * pixelSize; float y = (float)atlasSprite.borderTop * pixelSize; return this.mHighlightedLabel.cachedTransform.localPosition + new Vector3(-num, y, 1f); } private IEnumerator UpdateTweenPosition() { if (this.mHighlight != null && this.mHighlightedLabel != null) { TweenPosition tp = this.mHighlight.GetComponent(); while (tp != null && tp.enabled) { tp.to = this.GetHighlightPosition(); yield return null; } } this.mTweening = false; yield break; } private void OnItemHover(GameObject go, bool isOver) { if (isOver) { UILabel component = go.GetComponent(); this.Highlight(component, false); } } private void Select(UILabel lbl, bool instant) { this.Highlight(lbl, instant); UIEventListener component = lbl.gameObject.GetComponent(); this.value = (component.parameter as string); UIPlaySound[] components = base.GetComponents(); int i = 0; int num = components.Length; while (i < num) { UIPlaySound uiplaySound = components[i]; if (uiplaySound.trigger == UIPlaySound.Trigger.OnClick) { NGUITools.PlaySound(uiplaySound.audioClip, uiplaySound.volume, 1f); } i++; } } private void OnItemPress(GameObject go, bool isPressed) { if (isPressed) { this.Select(go.GetComponent(), true); } } private void OnItemClick(GameObject go) { this.Close(); } private void OnKey(KeyCode key) { if (base.enabled && NGUITools.GetActive(base.gameObject) && this.handleEvents) { int num = this.mLabelList.IndexOf(this.mHighlightedLabel); if (num == -1) { num = 0; } if (key == KeyCode.UpArrow) { if (num > 0) { this.Select(this.mLabelList[num - 1], false); } } else if (key == KeyCode.DownArrow) { if (num + 1 < this.mLabelList.Count) { this.Select(this.mLabelList[num + 1], false); } } else if (key == KeyCode.Escape) { this.OnSelect(false); } } } private void OnDisable() { this.Close(); } private void OnSelect(bool isSelected) { if (!isSelected) { this.Close(); } } public void Close() { if (this.mChild != null) { this.mLabelList.Clear(); this.handleEvents = false; if (this.isAnimated) { UIWidget[] componentsInChildren = this.mChild.GetComponentsInChildren(); int i = 0; int num = componentsInChildren.Length; while (i < num) { UIWidget uiwidget = componentsInChildren[i]; Color color = uiwidget.color; color.a = 0f; TweenColor.Begin(uiwidget.gameObject, 0.15f, color).method = UITweener.Method.EaseOut; i++; } Collider[] componentsInChildren2 = this.mChild.GetComponentsInChildren(); int j = 0; int num2 = componentsInChildren2.Length; while (j < num2) { componentsInChildren2[j].enabled = false; j++; } UnityEngine.Object.Destroy(this.mChild, 0.15f); } else { UnityEngine.Object.Destroy(this.mChild); } this.mBackground = null; this.mHighlight = null; this.mChild = null; } } private void AnimateColor(UIWidget widget) { Color color = widget.color; widget.color = new Color(color.r, color.g, color.b, 0f); TweenColor.Begin(widget.gameObject, 0.15f, color).method = UITweener.Method.EaseOut; } private void AnimatePosition(UIWidget widget, bool placeAbove, float bottom) { Vector3 localPosition = widget.cachedTransform.localPosition; Vector3 localPosition2 = (!placeAbove) ? new Vector3(localPosition.x, 0f, localPosition.z) : new Vector3(localPosition.x, bottom, localPosition.z); widget.cachedTransform.localPosition = localPosition2; GameObject gameObject = widget.gameObject; TweenPosition.Begin(gameObject, 0.15f, localPosition).method = UITweener.Method.EaseOut; } private void AnimateScale(UIWidget widget, bool placeAbove, float bottom) { GameObject gameObject = widget.gameObject; Transform cachedTransform = widget.cachedTransform; float num = (float)this.activeFontSize * this.activeFontScale + this.mBgBorder * 2f; cachedTransform.localScale = new Vector3(1f, num / (float)widget.height, 1f); TweenScale.Begin(gameObject, 0.15f, Vector3.one).method = UITweener.Method.EaseOut; if (placeAbove) { Vector3 localPosition = cachedTransform.localPosition; cachedTransform.localPosition = new Vector3(localPosition.x, localPosition.y - (float)widget.height + num, localPosition.z); TweenPosition.Begin(gameObject, 0.15f, localPosition).method = UITweener.Method.EaseOut; } } private void Animate(UIWidget widget, bool placeAbove, float bottom) { this.AnimateColor(widget); this.AnimatePosition(widget, placeAbove, bottom); } private void OnClick() { if (this.openOn == UIPopupList.OpenOn.DoubleClick || this.openOn == UIPopupList.OpenOn.Manual) { return; } if (this.openOn == UIPopupList.OpenOn.RightClick && UICamera.currentTouchID != -2) { return; } this.Show(); } private void OnDoubleClick() { if (this.openOn == UIPopupList.OpenOn.DoubleClick) { this.Show(); } } private IEnumerator CloseIfUnselected() { GameObject go = UICamera.selectedObject; do { yield return null; } while (!(UICamera.selectedObject != go)); this.Close(); yield break; } public void Show() { if (base.enabled && NGUITools.GetActive(base.gameObject) && this.mChild == null && this.atlas != null && this.isValid && this.items.Count > 0) { this.mLabelList.Clear(); if (this.mPanel == null) { this.mPanel = UIPanel.Find(base.transform); if (this.mPanel == null) { return; } } this.handleEvents = true; Transform transform = base.transform; this.mChild = new GameObject("Drop-down List"); this.mChild.layer = base.gameObject.layer; Transform transform2 = this.mChild.transform; transform2.parent = transform.parent; Vector3 vector; Vector3 v; Vector3 vector2; if (this.openOn == UIPopupList.OpenOn.Manual && UICamera.selectedObject != base.gameObject) { base.StopCoroutine("CloseIfUnselected"); vector = transform2.parent.InverseTransformPoint(this.mPanel.anchorCamera.ScreenToWorldPoint(UICamera.lastTouchPosition)); v = vector; transform2.localPosition = vector; vector2 = transform2.position; base.StartCoroutine("CloseIfUnselected"); } else { Bounds bounds = NGUIMath.CalculateRelativeWidgetBounds(transform.parent, transform, false, false); vector = bounds.min; v = bounds.max; transform2.localPosition = vector; vector2 = transform.position; } transform2.localRotation = Quaternion.identity; transform2.localScale = Vector3.one; this.mBackground = NGUITools.AddSprite(this.mChild, this.atlas, this.backgroundSprite); this.mBackground.pivot = UIWidget.Pivot.TopLeft; this.mBackground.depth = NGUITools.CalculateNextDepth(this.mPanel.gameObject); this.mBackground.color = this.backgroundColor; Vector4 border = this.mBackground.border; this.mBgBorder = border.y; this.mBackground.cachedTransform.localPosition = new Vector3(0f, border.y, 0f); this.mHighlight = NGUITools.AddSprite(this.mChild, this.atlas, this.highlightSprite); this.mHighlight.pivot = UIWidget.Pivot.TopLeft; this.mHighlight.color = this.highlightColor; UISpriteData atlasSprite = this.mHighlight.GetAtlasSprite(); if (atlasSprite == null) { return; } float num = (float)atlasSprite.borderTop; float num2 = (float)this.activeFontSize; float activeFontScale = this.activeFontScale; float num3 = num2 * activeFontScale; float num4 = 0f; float num5 = -this.padding.y; List list = new List(); if (!this.items.Contains(this.mSelectedItem)) { this.mSelectedItem = null; } int i = 0; int count = this.items.Count; while (i < count) { string text = this.items[i]; UILabel uilabel = NGUITools.AddWidget(this.mChild); uilabel.name = i.ToString(); uilabel.pivot = UIWidget.Pivot.TopLeft; uilabel.bitmapFont = this.bitmapFont; uilabel.trueTypeFont = this.trueTypeFont; uilabel.fontSize = this.fontSize; uilabel.fontStyle = this.fontStyle; uilabel.text = text; uilabel.color = this.textColor; uilabel.cachedTransform.localPosition = new Vector3(border.x + this.padding.x - uilabel.pivotOffset.x, num5, -1f); uilabel.overflowMethod = UILabel.Overflow.ResizeFreely; uilabel.alignment = this.alignment; list.Add(uilabel); if (this.isLocalized) { string term = text.Replace("\r", string.Empty); if (this.itemTerms != null && this.itemTerms.Count == this.items.Count && !string.IsNullOrEmpty(this.itemTerms[i])) { term = this.itemTerms[i]; } Localize localize = uilabel.gameObject.AddComponent(); localize.ForceOverFlowShrink = false; localize.SetTerm(term); NGUILabelLocalizeSupport component = uilabel.gameObject.GetComponent(); if (component != null) { component.overRidePropertys.overFlow.value = UILabel.Overflow.ResizeFreely; } } num5 -= num3; num5 -= this.padding.y; num4 = Mathf.Max(num4, uilabel.printedSize.x); UIEventListener uieventListener = UIEventListener.Get(uilabel.gameObject); uieventListener.onHover = new UIEventListener.BoolDelegate(this.OnItemHover); uieventListener.onPress = new UIEventListener.BoolDelegate(this.OnItemPress); uieventListener.onClick = new UIEventListener.VoidDelegate(this.OnItemClick); uieventListener.parameter = text; if (this.mSelectedItem == text || (i == 0 && string.IsNullOrEmpty(this.mSelectedItem))) { this.Highlight(uilabel, true); } this.mLabelList.Add(uilabel); i++; } num4 = Mathf.Max(num4, (v.x - vector.x) * activeFontScale - (border.x + this.padding.x) * 2f); float num6 = num4; Vector3 vector3 = new Vector3(num6 * 0.5f, -num3 * 0.5f, 0f); Vector3 vector4 = new Vector3(num6, num3 + this.padding.y, 1f); int j = 0; int count2 = list.Count; while (j < count2) { UILabel uilabel2 = list[j]; NGUITools.AddWidgetCollider(uilabel2.gameObject); uilabel2.autoResizeBoxCollider = false; BoxCollider component2 = uilabel2.GetComponent(); if (component2 != null) { vector3.z = component2.center.z; component2.center = vector3; component2.size = vector4; } else { BoxCollider2D component3 = uilabel2.GetComponent(); component3.offset = vector3; component3.size = vector4; } j++; } int width = Mathf.RoundToInt(num4); num4 += (border.x + this.padding.x) * 2f; num5 -= border.y; this.mBackground.width = Mathf.RoundToInt(num4); this.mBackground.height = Mathf.RoundToInt(-num5 + border.y); int k = 0; int count3 = list.Count; while (k < count3) { UILabel uilabel3 = list[k]; uilabel3.overflowMethod = UILabel.Overflow.ShrinkContent; uilabel3.width = width; k++; } float num7 = 2f * this.atlas.pixelSize; float f = num4 - (border.x + this.padding.x) * 2f + (float)atlasSprite.borderLeft * num7; float f2 = num3 + num * num7; this.mHighlight.width = Mathf.RoundToInt(f); this.mHighlight.height = Mathf.RoundToInt(f2); bool flag = this.position == UIPopupList.Position.Above; if (this.position == UIPopupList.Position.Auto) { UICamera uicamera = UICamera.FindCameraForLayer((UICamera.selectedObject ?? base.gameObject).layer); if (uicamera != null) { flag = (uicamera.cachedCamera.WorldToViewportPoint(vector2).y < 0.5f); } } if (this.isAnimated) { float bottom = num5 + num3; this.Animate(this.mHighlight, flag, bottom); int l = 0; int count4 = list.Count; while (l < count4) { this.Animate(list[l], flag, bottom); l++; } this.AnimateColor(this.mBackground); this.AnimateScale(this.mBackground, flag, bottom); } if (flag) { transform2.localPosition = new Vector3(vector.x, v.y - num5 - border.y, vector.z); } vector = transform2.localPosition; v.x = vector.x + (float)this.mBackground.width; v.y = vector.y - (float)this.mBackground.height; v.z = vector.z; Vector3 b = this.mPanel.CalculateConstrainOffset(vector, v); transform2.localPosition += b; } else { this.OnSelect(false); } } public static UIPopupList current; private const float animSpeed = 0.15f; public UIAtlas atlas; public UIFont bitmapFont; public Font trueTypeFont; public int fontSize = 16; public FontStyle fontStyle; public string backgroundSprite; public string highlightSprite; public UIPopupList.Position position; public NGUIText.Alignment alignment = NGUIText.Alignment.Left; public List items = new List(); public List itemTerms = new List(); public List itemData = new List(); public Vector2 padding = new Vector3(4f, 4f); public Color textColor = Color.white; public Color backgroundColor = Color.white; public Color highlightColor = new Color(0.88235295f, 0.78431374f, 0.5882353f, 1f); public bool isAnimated = true; public bool isLocalized; public UIPopupList.OpenOn openOn; public List onChange = new List(); [HideInInspector] [SerializeField] private string mSelectedItem; [HideInInspector] [SerializeField] private UIPanel mPanel; [HideInInspector] [SerializeField] private GameObject mChild; [HideInInspector] [SerializeField] private UISprite mBackground; [HideInInspector] [SerializeField] private UISprite mHighlight; [HideInInspector] [SerializeField] private UILabel mHighlightedLabel; [HideInInspector] [SerializeField] private List mLabelList = new List(); [HideInInspector] [SerializeField] private float mBgBorder; [HideInInspector] [SerializeField] private GameObject eventReceiver; [HideInInspector] [SerializeField] private string functionName = "OnSelectionChange"; [HideInInspector] [SerializeField] private float textScale; [HideInInspector] [SerializeField] private UIFont font; [HideInInspector] [SerializeField] private UILabel textLabel; private UIPopupList.LegacyEvent mLegacyEvent; private bool mUseDynamicFont; private bool mTweening; public enum Position { Auto, Above, Below } public enum OpenOn { ClickOrTap, RightClick, DoubleClick, Manual } public delegate void LegacyEvent(string val); }