Unity3D NGUI UIInput中文输入,插入文本时后面文本被删除问题

来源:互联网 发布:几何网络是什么意思 编辑:程序博客网 时间:2024/05/17 07:23

Unity的一个项目,这两天测试报了一个BUG,在电脑上输入中文时,如果插入文本会,后面的文本会被删除,经测试后发现NGUI Demo也有这个问题,估计是因为NGUI开发人员没有华人吧!改了下UIInput,有需要的朋友可以参考


NGUI 3.5.9   UIInput.cs 

//----------------------------------------------//            NGUI: Next-Gen UI kit// Copyright © 2011-2014 Tasharen Entertainment//----------------------------------------------#if !UNITY_EDITOR && (UNITY_IPHONE || UNITY_ANDROID || UNITY_WP8 || UNITY_BLACKBERRY)#define MOBILE#endifusing UnityEngine;using System.Collections.Generic;using System.Text;/// <summary>/// Input field makes it possible to enter custom information within the UI./// </summary>[AddComponentMenu("NGUI/UI/Input Field")]public class UIInput : MonoBehaviour{public enum InputType{Standard,AutoCorrect,Password,}public enum Validation{None,Integer,Float,Alphanumeric,Username,Name,}public enum KeyboardType{Default = 0,ASCIICapable = 1,NumbersAndPunctuation = 2,URL = 3,NumberPad = 4,PhonePad = 5,NamePhonePad = 6,EmailAddress = 7,}public enum OnReturnKey{Default,Submit,NewLine,}public delegate char OnValidate (string text, int charIndex, char addedChar);/// <summary>/// Currently active input field. Only valid during callbacks./// </summary>static public UIInput current;/// <summary>/// Currently selected input field, if any./// </summary>static public UIInput selection;/// <summary>/// Text label used to display the input's value./// </summary>public UILabel label;/// <summary>/// Type of data expected by the input field./// </summary>public InputType inputType = InputType.Standard;/// <summary>/// What to do when the Return key is pressed on the keyboard./// </summary>public OnReturnKey onReturnKey = OnReturnKey.Default;/// <summary>/// Keyboard type applies to mobile keyboards that get shown./// </summary>public KeyboardType keyboardType = KeyboardType.Default;/// <summary>/// What kind of validation to use with the input field's data./// </summary>public Validation validation = Validation.None;/// <summary>/// Maximum number of characters allowed before input no longer works./// </summary>public int characterLimit = 0;/// <summary>/// Field in player prefs used to automatically save the value./// </summary>public string savedAs;/// <summary>/// Object to select when Tab key gets pressed./// </summary>public GameObject selectOnTab;/// <summary>/// Color of the label when the input field has focus./// </summary>public Color activeTextColor = Color.white;/// <summary>/// Color used by the caret symbol./// </summary>public Color caretColor = new Color(1f, 1f, 1f, 0.8f);/// <summary>/// Color used by the selection rectangle./// </summary>public Color selectionColor = new Color(1f, 223f / 255f, 141f / 255f, 0.5f);/// <summary>/// Event delegates triggered when the input field submits its data./// </summary>public List<EventDelegate> onSubmit = new List<EventDelegate>();/// <summary>/// Event delegates triggered when the input field's text changes for any reason./// </summary>public List<EventDelegate> onChange = new List<EventDelegate>();/// <summary>/// Custom validation callback./// </summary>public OnValidate onValidate;/// <summary>/// Input field's value./// </summary>[SerializeField][HideInInspector] protected string mValue;protected string mDefaultText = "";protected Color mDefaultColor = Color.white;protected float mPosition = 0f;protected bool mDoInit = true;protected UIWidget.Pivot mPivot = UIWidget.Pivot.TopLeft;protected bool mLoadSavedValue = true;static protected int mDrawStart = 0;#if MOBILEstatic protected TouchScreenKeyboard mKeyboard;#elseprotected int mSelectionStart = 0;protected int mSelectionEnd = 0;protected UITexture mHighlight = null;protected UITexture mCaret = null;protected Texture2D mBlankTex = null;protected float mNextBlink = 0f;protected float mLastAlpha = 0f;static protected string mLastIME = "";#endif/// <summary>/// Default text used by the input's label./// </summary>public string defaultText{get{return mDefaultText;}set{if (mDoInit) Init();mDefaultText = value;UpdateLabel();}}[System.Obsolete("Use UIInput.value instead")]public string text { get { return this.value; } set { this.value = value; } }/// <summary>/// Input field's current text value./// </summary>public string value{get{#if UNITY_EDITORif (!Application.isPlaying) return "";#endifif (mDoInit) Init();return mValue;}set{#if UNITY_EDITORif (!Application.isPlaying) return;#endifif (mDoInit) Init();mDrawStart = 0;#if MOBILE && !UNITY_3_5// BB10's implementation has a bug in Unityif (Application.platform == RuntimePlatform.BB10Player)value = value.Replace("\\b", "\b");#endif// Validate all inputvalue = Validate(value);#if MOBILEif (isSelected && mKeyboard != null && mCached != value){mKeyboard.text = value;mCached = value;}if (mValue != value){mValue = value;mLoadSavedValue = false;if (!isSelected) SaveToPlayerPrefs(value);UpdateLabel();ExecuteOnChange();}#elseif (mValue != value){mValue = value;mLoadSavedValue = false;if (isSelected){if (string.IsNullOrEmpty(value)){mSelectionStart = 0;mSelectionEnd = 0;}else{mSelectionStart = value.Length;mSelectionEnd = mSelectionStart;}}else SaveToPlayerPrefs(value);UpdateLabel();ExecuteOnChange();}#endif}}[System.Obsolete("Use UIInput.isSelected instead")]public bool selected { get { return isSelected; } set { isSelected = value; } }/// <summary>/// Whether the input is currently selected./// </summary>public bool isSelected{get{return selection == this;}set{if (!value) { if (isSelected) UICamera.selectedObject = null; }else UICamera.selectedObject = gameObject;}}#if MOBILE/// <summary>/// Current position of the cursor./// </summary>public int cursorPosition { get { return value.Length; } set {} }/// <summary>/// Index of the character where selection begins./// </summary>public int selectionStart { get { return value.Length; } set {} }/// <summary>/// Index of the character where selection ends./// </summary>public int selectionEnd { get { return value.Length; } set {} }/// <summary>/// Caret, in case it's needed./// </summary>public UITexture caret { get { return null; } }#else/// <summary>/// Current position of the cursor./// </summary>public int cursorPosition{get{return isSelected ? mSelectionEnd : value.Length;}set{if (isSelected){mSelectionEnd = value;UpdateLabel();}}}/// <summary>/// Index of the character where selection begins./// </summary>public int selectionStart{get{return isSelected ? mSelectionStart : value.Length;}set{if (isSelected){mSelectionStart = value;UpdateLabel();}}}/// <summary>/// Index of the character where selection ends./// </summary>public int selectionEnd{get{return isSelected ? mSelectionEnd : value.Length;}set{if (isSelected){mSelectionEnd = value;UpdateLabel();}}}/// <summary>/// Caret, in case it's needed./// </summary>public UITexture caret { get { return mCaret; } }#endif/// <summary>/// Validate the specified text, returning the validated version./// </summary>public string Validate (string val){if (string.IsNullOrEmpty(val)) return "";StringBuilder sb = new StringBuilder(val.Length);for (int i = 0; i < val.Length; ++i){char c = val[i];if (onValidate != null) c = onValidate(sb.ToString(), sb.Length, c);else if (validation != Validation.None) c = Validate(sb.ToString(), sb.Length, c);if (c != 0) sb.Append(c);}if (characterLimit > 0 && sb.Length > characterLimit)return sb.ToString(0, characterLimit);return sb.ToString();}/// <summary>/// Automatically set the value by loading it from player prefs if possible./// </summary>void Start (){if (mLoadSavedValue && !string.IsNullOrEmpty(savedAs)) LoadValue();else value = mValue.Replace("\\n", "\n");}/// <summary>/// Labels used for input shouldn't support rich text./// </summary>protected void Init (){if (mDoInit && label != null){mDoInit = false;mDefaultText = label.text;mDefaultColor = label.color;label.supportEncoding = false;if (label.alignment == NGUIText.Alignment.Justified){label.alignment = NGUIText.Alignment.Left;Debug.LogWarning("Input fields using labels with justified alignment are not supported at this time", this);}mPivot = label.pivot;mPosition = label.cachedTransform.localPosition.x;UpdateLabel();}}/// <summary>/// Save the specified value to player prefs./// </summary>protected void SaveToPlayerPrefs (string val){if (!string.IsNullOrEmpty(savedAs)){if (string.IsNullOrEmpty(val)) PlayerPrefs.DeleteKey(savedAs);else PlayerPrefs.SetString(savedAs, val);}}/// <summary>/// Selection event, sent by the EventSystem./// </summary>protected virtual void OnSelect (bool isSelected){if (isSelected) OnSelectEvent();else OnDeselectEvent();}/// <summary>/// Notification of the input field gaining selection./// </summary>protected void OnSelectEvent (){selection = this;if (mDoInit) Init();if (label != null && NGUITools.GetActive(this)){label.color = activeTextColor;#if MOBILEif (Application.platform == RuntimePlatform.IPhonePlayer ||Application.platform == RuntimePlatform.Android#if UNITY_WP8|| Application.platform == RuntimePlatform.WP8Player#endif#if UNITY_BLACKBERRY|| Application.platform == RuntimePlatform.BB10Player#endif){mKeyboard = (inputType == InputType.Password) ?TouchScreenKeyboard.Open(mValue, TouchScreenKeyboardType.Default, false, false, true) :TouchScreenKeyboard.Open(mValue, (TouchScreenKeyboardType)((int)keyboardType), inputType == InputType.AutoCorrect, label.multiLine, false, false, defaultText);}else#endif{Vector2 pos = (UICamera.current != null && UICamera.current.cachedCamera != null) ?UICamera.current.cachedCamera.WorldToScreenPoint(label.worldCorners[0]) :label.worldCorners[0];pos.y = Screen.height - pos.y;Input.imeCompositionMode = IMECompositionMode.On;Input.compositionCursorPos = pos;#if !MOBILEmSelectionStart = 0;mSelectionEnd = string.IsNullOrEmpty(mValue) ? 0 : mValue.Length;#endifmDrawStart = 0;}UpdateLabel();}}/// <summary>/// Notification of the input field losing selection./// </summary>protected void OnDeselectEvent (){if (mDoInit) Init();if (label != null && NGUITools.GetActive(this)){mValue = value;#if MOBILEif (mKeyboard != null){mKeyboard.active = false;mKeyboard = null;}#endifif (string.IsNullOrEmpty(mValue)){label.text = mDefaultText;label.color = mDefaultColor;}else label.text = mValue;Input.imeCompositionMode = IMECompositionMode.Auto;RestoreLabelPivot();}selection = null;UpdateLabel();}/// <summary>/// Update the text based on input./// </summary>#if MOBILEstring mCached = "";void Update(){if (mKeyboard != null && isSelected){string text = mKeyboard.text;if (mCached != text){mCached = text;value = text;}if (mKeyboard.done || !mKeyboard.active){#if !UNITY_3_5if (!mKeyboard.wasCanceled)#endifSubmit();mKeyboard = null;isSelected = false;mCached = "";}}}#else//add by cjpstring inputString = "";//add by cjpvoid Update (){#if UNITY_EDITORif (!Application.isPlaying) return;#endifif (isSelected){if (mDoInit) Init();if (selectOnTab != null && Input.GetKeyDown(KeyCode.Tab)){UICamera.selectedObject = selectOnTab;return;}string ime = Input.compositionString;//add by cjpif(!string.IsNullOrEmpty(ime)&&!ime.Equals(inputString)&& ime.Length==1){Insert(""); } inputString = ime;//add by cjp// There seems to be an inconsistency between IME on Windows, and IME on OSX.// On Windows, Input.inputString is always empty while IME is active. On the OSX it is not.if (string.IsNullOrEmpty(ime) && !string.IsNullOrEmpty(Input.inputString)){// Process input ignoring non-printable characters as they are not consistent.// Windows has them, OSX may not. They get handled inside OnGUI() instead.string s = Input.inputString;for (int i = 0; i < s.Length; ++i){char ch = s[i];if (ch < ' ') continue;// OSX inserts these characters for arrow keysif (ch == '\uF700') continue;if (ch == '\uF701') continue;if (ch == '\uF702') continue;if (ch == '\uF703') continue;Insert(ch.ToString());}}// Append IME compositionif (mLastIME != ime){//add by cjp//mSelectionEnd = string.IsNullOrEmpty(ime) ? mSelectionStart : mValue.Length + ime.Length;mSelectionEnd = string.IsNullOrEmpty(ime) ? mSelectionStart : mSelectionStart + ime.Length;//add by cjpmLastIME = ime;UpdateLabel();ExecuteOnChange();}// Blink the caretif (mCaret != null && mNextBlink < RealTime.time){mNextBlink = RealTime.time + 0.5f;mCaret.enabled = !mCaret.enabled;}// If the label's final alpha changes, we need to update the drawn geometry,// or the highlight widgets (which have their geometry set manually) won't update.if (isSelected && mLastAlpha != label.finalAlpha)UpdateLabel();}}/// <summary>/// Unfortunately Unity 4.3 and earlier doesn't offer a way to properly process events outside of OnGUI./// </summary>void OnGUI (){if (isSelected && Event.current.rawType == EventType.KeyDown)ProcessEvent(Event.current);}/// <summary>/// Handle the specified event./// </summary>bool ProcessEvent (Event ev){if (label == null) return false;RuntimePlatform rp = Application.platform;bool isMac = (rp == RuntimePlatform.OSXEditor ||rp == RuntimePlatform.OSXPlayer ||rp == RuntimePlatform.OSXWebPlayer);bool ctrl = isMac ?((ev.modifiers & EventModifiers.Command) != 0) :((ev.modifiers & EventModifiers.Control) != 0);bool shift = ((ev.modifiers & EventModifiers.Shift) != 0);switch (ev.keyCode){case KeyCode.Backspace:{ev.Use();if (!string.IsNullOrEmpty(mValue)){if (mSelectionStart == mSelectionEnd){if (mSelectionStart < 1) return true;--mSelectionEnd;}Insert("");}return true;}case KeyCode.Delete:{ev.Use();if (!string.IsNullOrEmpty(mValue)){if (mSelectionStart == mSelectionEnd){if (mSelectionStart >= mValue.Length) return true;++mSelectionEnd;}Insert("");}return true;}case KeyCode.LeftArrow:{ev.Use();if (!string.IsNullOrEmpty(mValue)){mSelectionEnd = Mathf.Max(mSelectionEnd - 1, 0);if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}case KeyCode.RightArrow:{ev.Use();if (!string.IsNullOrEmpty(mValue)){mSelectionEnd = Mathf.Min(mSelectionEnd + 1, mValue.Length);if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}case KeyCode.PageUp:{ev.Use();if (!string.IsNullOrEmpty(mValue)){mSelectionEnd = 0;if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}case KeyCode.PageDown:{ev.Use();if (!string.IsNullOrEmpty(mValue)){mSelectionEnd = mValue.Length;if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}case KeyCode.Home:{ev.Use();if (!string.IsNullOrEmpty(mValue)){if (label.multiLine){mSelectionEnd = label.GetCharacterIndex(mSelectionEnd, KeyCode.Home);}else mSelectionEnd = 0;if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}case KeyCode.End:{ev.Use();if (!string.IsNullOrEmpty(mValue)){if (label.multiLine){mSelectionEnd = label.GetCharacterIndex(mSelectionEnd, KeyCode.End);}else mSelectionEnd = mValue.Length;if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}case KeyCode.UpArrow:{ev.Use();if (!string.IsNullOrEmpty(mValue)){mSelectionEnd = label.GetCharacterIndex(mSelectionEnd, KeyCode.UpArrow);if (mSelectionEnd != 0) mSelectionEnd += mDrawStart;if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}case KeyCode.DownArrow:{ev.Use();if (!string.IsNullOrEmpty(mValue)){mSelectionEnd = label.GetCharacterIndex(mSelectionEnd, KeyCode.DownArrow);if (mSelectionEnd != label.processedText.Length) mSelectionEnd += mDrawStart;else mSelectionEnd = mValue.Length;if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}// Copycase KeyCode.C:{if (ctrl){ev.Use();NGUITools.clipboard = GetSelection();}return true;}// Pastecase KeyCode.V:{if (ctrl){ev.Use();Insert(NGUITools.clipboard);}return true;}// Cutcase KeyCode.X:{if (ctrl){ev.Use();NGUITools.clipboard = GetSelection();Insert("");}return true;}// Submitcase KeyCode.Return:case KeyCode.KeypadEnter:{ev.Use();bool newLine = (onReturnKey == OnReturnKey.NewLine) ||(onReturnKey == OnReturnKey.Default &&label.multiLine && !ctrl &&label.overflowMethod != UILabel.Overflow.ClampContent &&validation == Validation.None);if (newLine){Insert("\n");}else{UICamera.currentScheme = UICamera.ControlScheme.Controller;UICamera.currentKey = ev.keyCode;Submit();UICamera.currentKey = KeyCode.None;}return true;}}return false;}/// <summary>/// Insert the specified text string into the current input value, respecting selection and validation./// </summary>protected virtual void Insert (string text){string left = GetLeftText();string right = GetRightText();int rl = right.Length;StringBuilder sb = new StringBuilder(left.Length + right.Length + text.Length);sb.Append(left);// Append the new textfor (int i = 0, imax = text.Length; i < imax; ++i){// Can't go past the character limitif (characterLimit > 0 && sb.Length + rl >= characterLimit) break;// If we have an input validator, validate the input firstchar c = text[i];if (onValidate != null) c = onValidate(sb.ToString(), sb.Length, c);else if (validation != Validation.None) c = Validate(sb.ToString(), sb.Length, c);// Append the character if it hasn't been invalidatedif (c != 0) sb.Append(c);}// Advance the selectionmSelectionStart = sb.Length;mSelectionEnd = mSelectionStart;// Append the text that follows it, ensuring that it's also validated after the inserted valuefor (int i = 0, imax = right.Length; i < imax; ++i){char c = right[i];if (onValidate != null) c = onValidate(sb.ToString(), sb.Length, c);else if (validation != Validation.None) c = Validate(sb.ToString(), sb.Length, c);if (c != 0) sb.Append(c);}mValue = sb.ToString();UpdateLabel();ExecuteOnChange();}/// <summary>/// Get the text to the left of the selection./// </summary>protected string GetLeftText (){int min = Mathf.Min(mSelectionStart, mSelectionEnd);return (string.IsNullOrEmpty(mValue) || min < 0) ? "" : mValue.Substring(0, min);}/// <summary>/// Get the text to the right of the selection./// </summary>protected string GetRightText (){int max = Mathf.Max(mSelectionStart, mSelectionEnd);//add by cjp//return (string.IsNullOrEmpty(mValue) || max >= mValue.Length) ? "" : mValue.Substring(max);string v = label.text;return (string.IsNullOrEmpty(v) || max >= v.Length) ? "" : v.Substring(max);//add by cjp}/// <summary>/// Get currently selected text./// </summary>protected string GetSelection (){if (string.IsNullOrEmpty(mValue) || mSelectionStart == mSelectionEnd){return "";}else{int min = Mathf.Min(mSelectionStart, mSelectionEnd);int max = Mathf.Max(mSelectionStart, mSelectionEnd);//add by cjpmin = Mathf.Min(min, mValue.Length);max = Mathf.Min(max, mValue.Length);//add by cjpreturn mValue.Substring(min, max - min);}}/// <summary>/// Helper function that retrieves the index of the character under the mouse./// </summary>protected int GetCharUnderMouse (){Vector3[] corners = label.worldCorners;Ray ray = UICamera.currentRay;Plane p = new Plane(corners[0], corners[1], corners[2]);float dist;return p.Raycast(ray, out dist) ? mDrawStart + label.GetCharacterIndexAtPosition(ray.GetPoint(dist)) : 0;}/// <summary>/// Move the caret on press./// </summary>protected virtual void OnPress (bool isPressed){if (isPressed && isSelected && label != null && UICamera.currentScheme == UICamera.ControlScheme.Mouse){mSelectionEnd = GetCharUnderMouse();if (!Input.GetKey(KeyCode.LeftShift) &&!Input.GetKey(KeyCode.RightShift)) mSelectionStart = mSelectionEnd;UpdateLabel();}}/// <summary>/// Drag selection./// </summary>protected virtual void OnDrag (Vector2 delta){if (label != null && UICamera.currentScheme == UICamera.ControlScheme.Mouse){mSelectionEnd = GetCharUnderMouse();UpdateLabel();}}/// <summary>/// Ensure we've released the dynamically created resources./// </summary>void OnDisable () { Cleanup(); }/// <summary>/// Cleanup./// </summary>protected virtual void Cleanup (){if (mHighlight) mHighlight.enabled = false;if (mCaret) mCaret.enabled = false;if (mBlankTex){NGUITools.Destroy(mBlankTex);mBlankTex = null;}}#endif // !MOBILE/// <summary>/// Submit the input field's text./// </summary>public void Submit (){if (NGUITools.GetActive(this)){mValue = value;if (current == null){current = this;EventDelegate.Execute(onSubmit);current = null;}SaveToPlayerPrefs(mValue);}}/// <summary>/// Update the visual text label./// </summary>public void UpdateLabel (){if (label != null){if (mDoInit) Init();bool selected = isSelected;string fullText = value;bool isEmpty = string.IsNullOrEmpty(fullText) && string.IsNullOrEmpty(Input.compositionString);label.color = (isEmpty && !selected) ? mDefaultColor : activeTextColor;string processed;if (isEmpty){processed = selected ? "" : mDefaultText;RestoreLabelPivot();}else{if (inputType == InputType.Password){processed = "";string asterisk = "*";if (label.bitmapFont != null && label.bitmapFont.bmFont != null &&label.bitmapFont.bmFont.GetGlyph('*') == null) asterisk = "x";for (int i = 0, imax = fullText.Length; i < imax; ++i) processed += asterisk;}else processed = fullText;// Start with text leading up to the selection//add by cjp// int selPos = selected ? Mathf.Min(processed.Length, cursorPosition) : 0;int selPos = selected ? Mathf.Min(processed.Length, mSelectionStart) : 0;//add by cjpstring left = processed.Substring(0, selPos);// Append the composition string and the cursor characterif (selected) left += Input.compositionString;// Append the text from the selection onwardsprocessed = left + processed.Substring(selPos, processed.Length - selPos);// Clamped content needs to be adjusted furtherif (selected && label.overflowMethod == UILabel.Overflow.ClampContent){// Determine what will actually fit into the given lineint offset = label.CalculateOffsetToFit(processed);if (offset == 0){mDrawStart = 0;RestoreLabelPivot();}else if (selPos < mDrawStart){mDrawStart = selPos;SetPivotToLeft();}else if (offset < mDrawStart){mDrawStart = offset;SetPivotToLeft();}else{offset = label.CalculateOffsetToFit(processed.Substring(0, selPos));if (offset > mDrawStart){mDrawStart = offset;SetPivotToRight();}}// If necessary, trim the frontif (mDrawStart != 0)processed = processed.Substring(mDrawStart, processed.Length - mDrawStart);}else{mDrawStart = 0;RestoreLabelPivot();}}label.text = processed;#if !MOBILEif (selected){int start = mSelectionStart - mDrawStart;int end = mSelectionEnd - mDrawStart;// Blank texture used by selection and caretif (mBlankTex == null){mBlankTex = new Texture2D(2, 2, TextureFormat.ARGB32, false);for (int y = 0; y < 2; ++y)for (int x = 0; x < 2; ++x)mBlankTex.SetPixel(x, y, Color.white);mBlankTex.Apply();}// Create the selection highlightif (start != end){if (mHighlight == null){mHighlight = NGUITools.AddWidget<UITexture>(label.cachedGameObject);mHighlight.name = "Input Highlight";mHighlight.mainTexture = mBlankTex;mHighlight.fillGeometry = false;mHighlight.pivot = label.pivot;mHighlight.SetAnchor(label.cachedTransform);}else{mHighlight.pivot = label.pivot;mHighlight.mainTexture = mBlankTex;mHighlight.MarkAsChanged();mHighlight.enabled = true;}}// Create the caretif (mCaret == null){mCaret = NGUITools.AddWidget<UITexture>(label.cachedGameObject);mCaret.name = "Input Caret";mCaret.mainTexture = mBlankTex;mCaret.fillGeometry = false;mCaret.pivot = label.pivot;mCaret.SetAnchor(label.cachedTransform);}else{mCaret.pivot = label.pivot;mCaret.mainTexture = mBlankTex;mCaret.MarkAsChanged();mCaret.enabled = true;}if (start != end){label.PrintOverlay(start, end, mCaret.geometry, mHighlight.geometry, caretColor, selectionColor);mHighlight.enabled = mHighlight.geometry.hasVertices;}else{label.PrintOverlay(start, end, mCaret.geometry, null, caretColor, selectionColor);if (mHighlight != null) mHighlight.enabled = false;}// Reset the blinking timemNextBlink = RealTime.time + 0.5f;mLastAlpha = label.finalAlpha;}else Cleanup();#endif}}/// <summary>/// Set the label's pivot to the left./// </summary>protected void SetPivotToLeft (){Vector2 po = NGUIMath.GetPivotOffset(mPivot);po.x = 0f;label.pivot = NGUIMath.GetPivot(po);}/// <summary>/// Set the label's pivot to the right./// </summary>protected void SetPivotToRight (){Vector2 po = NGUIMath.GetPivotOffset(mPivot);po.x = 1f;label.pivot = NGUIMath.GetPivot(po);}/// <summary>/// Restore the input label's pivot point./// </summary>protected void RestoreLabelPivot (){if (label != null && label.pivot != mPivot)label.pivot = mPivot;}/// <summary>/// Validate the specified input./// </summary>protected char Validate (string text, int pos, char ch){// Validation is disabledif (validation == Validation.None || !enabled) return ch;if (validation == Validation.Integer){// Integer number validationif (ch >= '0' && ch <= '9') return ch;if (ch == '-' && pos == 0 && !text.Contains("-")) return ch;}else if (validation == Validation.Float){// Floating-point numberif (ch >= '0' && ch <= '9') return ch;if (ch == '-' && pos == 0 && !text.Contains("-")) return ch;if (ch == '.' && !text.Contains(".")) return ch;}else if (validation == Validation.Alphanumeric){// All alphanumeric charactersif (ch >= 'A' && ch <= 'Z') return ch;if (ch >= 'a' && ch <= 'z') return ch;if (ch >= '0' && ch <= '9') return ch;}else if (validation == Validation.Username){// Lowercase and numbersif (ch >= 'A' && ch <= 'Z') return (char)(ch - 'A' + 'a');if (ch >= 'a' && ch <= 'z') return ch;if (ch >= '0' && ch <= '9') return ch;}else if (validation == Validation.Name){char lastChar = (text.Length > 0) ? text[Mathf.Clamp(pos, 0, text.Length - 1)] : ' ';char nextChar = (text.Length > 0) ? text[Mathf.Clamp(pos + 1, 0, text.Length - 1)] : '\n';if (ch >= 'a' && ch <= 'z'){// Space followed by a letter -- make sure it's capitalizedif (lastChar == ' ') return (char)(ch - 'a' + 'A');return ch;}else if (ch >= 'A' && ch <= 'Z'){// Uppercase letters are only allowed after spaces (and apostrophes)if (lastChar != ' ' && lastChar != '\'') return (char)(ch - 'A' + 'a');return ch;}else if (ch == '\''){// Don't allow more than one apostropheif (lastChar != ' ' && lastChar != '\'' && nextChar != '\'' && !text.Contains("'")) return ch;}else if (ch == ' '){// Don't allow more than one space in a rowif (lastChar != ' ' && lastChar != '\'' && nextChar != ' ' && nextChar != '\'') return ch;}}return (char)0;}/// <summary>/// Execute the OnChange callback./// </summary>protected void ExecuteOnChange (){if (current == null && EventDelegate.IsValid(onChange)){current = this;EventDelegate.Execute(onChange);current = null;}}/// <summary>/// Convenience function to be used as a callback that will clear the input field's focus./// </summary>public void RemoveFocus () { isSelected = false; }/// <summary>/// Convenience function that can be used as a callback for On Change notification./// </summary>public void SaveValue () { SaveToPlayerPrefs(mValue); }/// <summary>/// Convenience function that can forcefully reset the input field's value to what was saved earlier./// </summary>public void LoadValue (){if (!string.IsNullOrEmpty(savedAs) && PlayerPrefs.HasKey(savedAs))value = PlayerPrefs.GetString(savedAs);}}


NGUI 3.11.2   UIInput.cs 


//-------------------------------------------------//            NGUI: Next-Gen UI kit// Copyright © 2011-2017 Tasharen Entertainment Inc//-------------------------------------------------#if !UNITY_EDITOR && (UNITY_IPHONE || UNITY_ANDROID || UNITY_WP8 || UNITY_WP_8_1 || UNITY_BLACKBERRY || UNITY_WINRT || UNITY_METRO)#define MOBILE#endifusing UnityEngine;using System.Collections.Generic;using System.Text;/// <summary>/// Input field makes it possible to enter custom information within the UI./// </summary>[AddComponentMenu("NGUI/UI/Input Field")]public class UIInput : MonoBehaviour{public enum InputType{Standard,AutoCorrect,Password,}public enum Validation{None,Integer,Float,Alphanumeric,Username,Name,Filename,}#if UNITY_EDITORpublic enum KeyboardType{Default = (int)TouchScreenKeyboardType.Default,ASCIICapable = (int)TouchScreenKeyboardType.ASCIICapable,NumbersAndPunctuation = (int)TouchScreenKeyboardType.NumbersAndPunctuation,URL = (int)TouchScreenKeyboardType.URL,NumberPad = (int)TouchScreenKeyboardType.NumberPad,PhonePad = (int)TouchScreenKeyboardType.PhonePad,NamePhonePad = (int)TouchScreenKeyboardType.NamePhonePad,EmailAddress = (int)TouchScreenKeyboardType.EmailAddress,}#elsepublic enum KeyboardType{Default = 0,ASCIICapable = 1,NumbersAndPunctuation = 2,URL = 3,NumberPad = 4,PhonePad = 5,NamePhonePad = 6,EmailAddress = 7,}#endifpublic enum OnReturnKey{Default,Submit,NewLine,}public delegate char OnValidate (string text, int charIndex, char addedChar);/// <summary>/// Currently active input field. Only valid during callbacks./// </summary>static public UIInput current;/// <summary>/// Currently selected input field, if any./// </summary>static public UIInput selection;/// <summary>/// Text label used to display the input's value./// </summary>public UILabel label;/// <summary>/// Type of data expected by the input field./// </summary>public InputType inputType = InputType.Standard;/// <summary>/// What to do when the Return key is pressed on the keyboard./// </summary>public OnReturnKey onReturnKey = OnReturnKey.Default;/// <summary>/// Keyboard type applies to mobile keyboards that get shown./// </summary>public KeyboardType keyboardType = KeyboardType.Default;/// <summary>/// Whether the input will be hidden on mobile platforms./// </summary>public bool hideInput = false;/// <summary>/// Whether all text will be selected when the input field gains focus./// </summary>[System.NonSerialized]public bool selectAllTextOnFocus = true;/// <summary>/// What kind of validation to use with the input field's data./// </summary>public Validation validation = Validation.None;/// <summary>/// Maximum number of characters allowed before input no longer works./// </summary>public int characterLimit = 0;/// <summary>/// Field in player prefs used to automatically save the value./// </summary>public string savedAs;/// <summary>/// Don't use this anymore. Attach UIKeyNavigation instead./// </summary>[HideInInspector][SerializeField] GameObject selectOnTab;/// <summary>/// Color of the label when the input field has focus./// </summary>public Color activeTextColor = Color.white;/// <summary>/// Color used by the caret symbol./// </summary>public Color caretColor = new Color(1f, 1f, 1f, 0.8f);/// <summary>/// Color used by the selection rectangle./// </summary>public Color selectionColor = new Color(1f, 223f / 255f, 141f / 255f, 0.5f);/// <summary>/// Event delegates triggered when the input field submits its data./// </summary>public List<EventDelegate> onSubmit = new List<EventDelegate>();/// <summary>/// Event delegates triggered when the input field's text changes for any reason./// </summary>public List<EventDelegate> onChange = new List<EventDelegate>();/// <summary>/// Custom validation callback./// </summary>public OnValidate onValidate;/// <summary>/// Input field's value./// </summary>[SerializeField][HideInInspector] protected string mValue;[System.NonSerialized] protected string mDefaultText = "";[System.NonSerialized] protected Color mDefaultColor = Color.white;[System.NonSerialized] protected float mPosition = 0f;[System.NonSerialized] protected bool mDoInit = true;[System.NonSerialized] protected NGUIText.Alignment mAlignment = NGUIText.Alignment.Left;[System.NonSerialized] protected bool mLoadSavedValue = true;static protected int mDrawStart = 0;static protected string mLastIME = "";#if MOBILE// Unity fails to compile if the touch screen keyboard is used on a non-mobile devicestatic protected TouchScreenKeyboard mKeyboard;static bool mWaitForKeyboard = false;#endif[System.NonSerialized] protected int mSelectionStart = 0;[System.NonSerialized] protected int mSelectionEnd = 0;[System.NonSerialized] protected UITexture mHighlight = null;[System.NonSerialized] protected UITexture mCaret = null;[System.NonSerialized] protected Texture2D mBlankTex = null;[System.NonSerialized] protected float mNextBlink = 0f;[System.NonSerialized] protected float mLastAlpha = 0f;[System.NonSerialized] protected string mCached = "";[System.NonSerialized] protected int mSelectMe = -1;[System.NonSerialized] protected int mSelectTime = -1;[System.NonSerialized] protected bool mStarted = false;/// <summary>/// Default text used by the input's label./// </summary>public string defaultText{get{if (mDoInit) Init();return mDefaultText;}set{if (mDoInit) Init();mDefaultText = value;UpdateLabel();}}/// <summary>/// Text's default color when not selected./// </summary>public Color defaultColor{get{if (mDoInit) Init();return mDefaultColor;}set{mDefaultColor = value;if (!isSelected) label.color = value;}}/// <summary>/// Should the input be hidden?/// </summary>public bool inputShouldBeHidden{get{return hideInput && label != null && !label.multiLine && inputType != InputType.Password;}}[System.Obsolete("Use UIInput.value instead")]public string text { get { return this.value; } set { this.value = value; } }/// <summary>/// Input field's current text value./// </summary>public string value{get{#if UNITY_EDITORif (!Application.isPlaying) return "";#endifif (mDoInit) Init();return mValue;}set { Set(value); }}/// <summary>/// Set the input field's value. If setting the initial value, call Start() first./// </summary>public void Set (string value, bool notify = true){#if UNITY_EDITORif (!Application.isPlaying) return;#endifif (mDoInit) Init();if (value == this.value) return;mDrawStart = 0;// BB10's implementation has a bug in Unity#if UNITY_4_3if (Application.platform == RuntimePlatform.BB10Player)value = value.Replace("\\b", "\b");#elif UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2 || UNITY_5_3if (Application.platform == RuntimePlatform.BlackBerryPlayer)value = value.Replace("\\b", "\b");#endif// Validate all inputvalue = Validate(value);#if MOBILEif (isSelected && mKeyboard != null && mCached != value){mKeyboard.text = value;mCached = value;}#endifif (mValue != value){mValue = value;mLoadSavedValue = false;if (isSelected){if (string.IsNullOrEmpty(value)){mSelectionStart = 0;mSelectionEnd = 0;}else{mSelectionStart = value.Length;mSelectionEnd = mSelectionStart;}}else if (mStarted) SaveToPlayerPrefs(value);UpdateLabel();if (notify) ExecuteOnChange();}}[System.Obsolete("Use UIInput.isSelected instead")]public bool selected { get { return isSelected; } set { isSelected = value; } }/// <summary>/// Whether the input is currently selected./// </summary>public bool isSelected{get{return selection == this;}set{if (!value) { if (isSelected) UICamera.selectedObject = null; }else UICamera.selectedObject = gameObject;}}/// <summary>/// Current position of the cursor./// </summary>public int cursorPosition{get{#if MOBILEif (mKeyboard != null && !inputShouldBeHidden) return value.Length;#endifreturn isSelected ? mSelectionEnd : value.Length;}set{if (isSelected){#if MOBILEif (mKeyboard != null && !inputShouldBeHidden) return;#endifmSelectionEnd = value;UpdateLabel();}}}/// <summary>/// Index of the character where selection begins./// </summary>public int selectionStart{get{#if MOBILEif (mKeyboard != null && !inputShouldBeHidden) return 0;#endifreturn isSelected ? mSelectionStart : value.Length;}set{if (isSelected){#if MOBILEif (mKeyboard != null && !inputShouldBeHidden) return;#endifmSelectionStart = value;UpdateLabel();}}}/// <summary>/// Index of the character where selection ends./// </summary>public int selectionEnd{get{#if MOBILEif (mKeyboard != null && !inputShouldBeHidden) return value.Length;#endifreturn isSelected ? mSelectionEnd : value.Length;}set{if (isSelected){#if MOBILEif (mKeyboard != null && !inputShouldBeHidden) return;#endifmSelectionEnd = value;UpdateLabel();}}}/// <summary>/// Caret, in case it's needed./// </summary>public UITexture caret { get { return mCaret; } }/// <summary>/// Validate the specified text, returning the validated version./// </summary>public string Validate (string val){if (string.IsNullOrEmpty(val)) return "";StringBuilder sb = new StringBuilder(val.Length);for (int i = 0; i < val.Length; ++i){char c = val[i];if (onValidate != null) c = onValidate(sb.ToString(), sb.Length, c);else if (validation != Validation.None) c = Validate(sb.ToString(), sb.Length, c);if (c != 0) sb.Append(c);}if (characterLimit > 0 && sb.Length > characterLimit)return sb.ToString(0, characterLimit);return sb.ToString();}/// <summary>/// Automatically set the value by loading it from player prefs if possible./// </summary>public void Start (){if (mStarted) return;if (selectOnTab != null){UIKeyNavigation nav = GetComponent<UIKeyNavigation>();if (nav == null){nav = gameObject.AddComponent<UIKeyNavigation>();nav.onDown = selectOnTab;}selectOnTab = null;NGUITools.SetDirty(this);}if (mLoadSavedValue && !string.IsNullOrEmpty(savedAs)) LoadValue();else value = mValue.Replace("\\n", "\n");mStarted = true;}/// <summary>/// Labels used for input shouldn't support rich text./// </summary>protected void Init (){if (mDoInit && label != null){mDoInit = false;mDefaultText = label.text;mDefaultColor = label.color;mEllipsis = label.overflowEllipsis;if (label.alignment == NGUIText.Alignment.Justified){label.alignment = NGUIText.Alignment.Left;Debug.LogWarning("Input fields using labels with justified alignment are not supported at this time", this);}mAlignment = label.alignment;mPosition = label.cachedTransform.localPosition.x;UpdateLabel();}}/// <summary>/// Save the specified value to player prefs./// </summary>protected void SaveToPlayerPrefs (string val){if (!string.IsNullOrEmpty(savedAs)){if (string.IsNullOrEmpty(val)) PlayerPrefs.DeleteKey(savedAs);else PlayerPrefs.SetString(savedAs, val);}}#if !MOBILE[System.NonSerialized] UIInputOnGUI mOnGUI;#endif[System.NonSerialized] UICamera mCam;/// <summary>/// Selection event, sent by the EventSystem./// </summary>protected virtual void OnSelect (bool isSelected){if (isSelected){if (label != null) label.supportEncoding = false;#if !MOBILEif (mOnGUI == null)mOnGUI = gameObject.AddComponent<UIInputOnGUI>();#endifOnSelectEvent();}else{#if !MOBILEif (mOnGUI != null){Destroy(mOnGUI);mOnGUI = null;}#endifOnDeselectEvent();}}/// <summary>/// Notification of the input field gaining selection./// </summary>protected void OnSelectEvent (){mSelectTime = Time.frameCount;selection = this;if (mDoInit) Init();if (label != null){mEllipsis = label.overflowEllipsis;label.overflowEllipsis = false;}// Unity has issues bringing up the keyboard properly if it's in "hideInput" mode and you happen// to select one input in the same Update as de-selecting another.if (label != null && NGUITools.GetActive(this)) mSelectMe = Time.frameCount;}[System.NonSerialized] bool mEllipsis = false;/// <summary>/// Notification of the input field losing selection./// </summary>protected void OnDeselectEvent (){if (mDoInit) Init();if (label != null) label.overflowEllipsis = mEllipsis;if (label != null && NGUITools.GetActive(this)){mValue = value;#if MOBILEif (mKeyboard != null){mWaitForKeyboard = false;mKeyboard.active = false;mKeyboard = null;}#endifif (string.IsNullOrEmpty(mValue)){label.text = mDefaultText;label.color = mDefaultColor;}else label.text = mValue;Input.imeCompositionMode = IMECompositionMode.Auto;label.alignment = mAlignment;}selection = null;UpdateLabel();}//add by cjpstring inputString = "";//add by cjp/// <summary>/// Update the text based on input./// </summary>protected virtual void Update (){#if UNITY_EDITORif (!Application.isPlaying) return;#endifif (!isSelected || mSelectTime == Time.frameCount) return;if (mDoInit) Init();#if MOBILE// Wait for the keyboard to open. Apparently mKeyboard.active will return 'false' for a while in some cases.if (mWaitForKeyboard){if (mKeyboard != null && !mKeyboard.active) return;mWaitForKeyboard = false;}#endif// Unity has issues bringing up the keyboard properly if it's in "hideInput" mode and you happen// to select one input in the same Update as de-selecting another.if (mSelectMe != -1 && mSelectMe != Time.frameCount){mSelectMe = -1;mSelectionEnd = string.IsNullOrEmpty(mValue) ? 0 : mValue.Length;mDrawStart = 0;mSelectionStart = selectAllTextOnFocus ? 0 : mSelectionEnd;label.color = activeTextColor;#if MOBILERuntimePlatform pf = Application.platform;if (pf == RuntimePlatform.IPhonePlayer|| pf == RuntimePlatform.Android|| pf == RuntimePlatform.WP8Player #if UNITY_4_3|| pf == RuntimePlatform.BB10Player #else|| pf == RuntimePlatform.BlackBerryPlayer|| pf == RuntimePlatform.MetroPlayerARM|| pf == RuntimePlatform.MetroPlayerX64|| pf == RuntimePlatform.MetroPlayerX86 #endif){string val;TouchScreenKeyboardType kt;if (inputShouldBeHidden){TouchScreenKeyboard.hideInput = true;kt = (TouchScreenKeyboardType)((int)keyboardType);val = "|";}else if (inputType == InputType.Password){TouchScreenKeyboard.hideInput = false;kt = (TouchScreenKeyboardType)((int)keyboardType);val = mValue;mSelectionStart = mSelectionEnd;}else{TouchScreenKeyboard.hideInput = false;kt = (TouchScreenKeyboardType)((int)keyboardType);val = mValue;mSelectionStart = mSelectionEnd;}mWaitForKeyboard = true;mKeyboard = (inputType == InputType.Password) ?TouchScreenKeyboard.Open(val, kt, false, false, true) :TouchScreenKeyboard.Open(val, kt, !inputShouldBeHidden && inputType == InputType.AutoCorrect,label.multiLine && !hideInput, false, false, defaultText);#if UNITY_METROmKeyboard.active = true;#endif}else#endif // MOBILE{Vector2 pos = (UICamera.current != null && UICamera.current.cachedCamera != null) ?UICamera.current.cachedCamera.WorldToScreenPoint(label.worldCorners[0]) :label.worldCorners[0];pos.y = Screen.height - pos.y;Input.imeCompositionMode = IMECompositionMode.On;Input.compositionCursorPos = pos;}UpdateLabel();if (string.IsNullOrEmpty(Input.inputString)) return;}#if MOBILEif (mKeyboard != null){string text = (mKeyboard.done || !mKeyboard.active) ? mCached : mKeyboard.text; if (inputShouldBeHidden){if (text != "|"){if (!string.IsNullOrEmpty(text)){Insert(text.Substring(1));}else if (!mKeyboard.done && mKeyboard.active){DoBackspace();}mKeyboard.text = "|";}}else if (mCached != text){mCached = text;if (!mKeyboard.done && mKeyboard.active) value = text;}if (mKeyboard.done || !mKeyboard.active){if (!mKeyboard.wasCanceled) Submit();mKeyboard = null;isSelected = false;mCached = "";}}else#endif // MOBILE{string ime = Input.compositionString;//add by cjpif(!string.IsNullOrEmpty(ime)&&!ime.Equals(inputString)&& ime.Length==1){Insert(""); } inputString = ime;//add by cjp// There seems to be an inconsistency between IME on Windows, and IME on OSX.// On Windows, Input.inputString is always empty while IME is active. On the OSX it is not.if (string.IsNullOrEmpty(ime) && !string.IsNullOrEmpty(Input.inputString)){// Process input ignoring non-printable characters as they are not consistent.// Windows has them, OSX may not. They get handled inside OnGUI() instead.string s = Input.inputString;for (int i = 0; i < s.Length; ++i){char ch = s[i];if (ch < ' ') continue;// OSX inserts these characters for arrow keysif (ch == '\uF700') continue;if (ch == '\uF701') continue;if (ch == '\uF702') continue;if (ch == '\uF703') continue;if (ch == '\uF728') continue;Insert(ch.ToString());}}// Append IME compositionif (mLastIME != ime){//add by cjp//mSelectionEnd = string.IsNullOrEmpty(ime) ? mSelectionStart : mValue.Length + ime.Length;mSelectionEnd = string.IsNullOrEmpty(ime) ? mSelectionStart : mSelectionStart + ime.Length;//add by cjpmLastIME = ime;UpdateLabel();ExecuteOnChange();}}// Blink the caretif (mCaret != null && mNextBlink < RealTime.time){mNextBlink = RealTime.time + 0.5f;mCaret.enabled = !mCaret.enabled;}// If the label's final alpha changes, we need to update the drawn geometry,// or the highlight widgets (which have their geometry set manually) won't update.if (isSelected && mLastAlpha != label.finalAlpha)UpdateLabel();// Cache the cameraif (mCam == null) mCam = UICamera.FindCameraForLayer(gameObject.layer);// Having this in OnGUI causes issues because Input.inputString gets updated *after* OnGUI, apparently...if (mCam != null){bool newLine = false;if (label.multiLine){bool ctrl = Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl);if (onReturnKey == OnReturnKey.Submit) newLine = ctrl;else newLine = !ctrl;}if (UICamera.GetKeyDown(mCam.submitKey0) || (mCam.submitKey0 == KeyCode.Return && UICamera.GetKeyDown(KeyCode.KeypadEnter))){if (newLine){Insert("\n");}else{if (UICamera.controller.current != null)UICamera.controller.clickNotification = UICamera.ClickNotification.None;UICamera.currentKey = mCam.submitKey0;Submit();}}if (UICamera.GetKeyDown(mCam.submitKey1) || (mCam.submitKey1 == KeyCode.Return && UICamera.GetKeyDown(KeyCode.KeypadEnter))){if (newLine){Insert("\n");}else{if (UICamera.controller.current != null)UICamera.controller.clickNotification = UICamera.ClickNotification.None;UICamera.currentKey = mCam.submitKey1;Submit();}}if (!mCam.useKeyboard && UICamera.GetKeyUp(KeyCode.Tab))OnKey(KeyCode.Tab);}}static int mIgnoreKey = 0;void OnKey (KeyCode key){int frame = Time.frameCount;if (mIgnoreKey == frame) return;if (mCam != null && (key == mCam.cancelKey0 || key == mCam.cancelKey1)){mIgnoreKey = frame;isSelected = false;}else if (key == KeyCode.Tab){mIgnoreKey = frame;isSelected = false;UIKeyNavigation nav = GetComponent<UIKeyNavigation>();if (nav != null) nav.OnKey(KeyCode.Tab);}}/// <summary>/// Perform a backspace operation./// </summary>protected void DoBackspace (){if (!string.IsNullOrEmpty(mValue)){if (mSelectionStart == mSelectionEnd){if (mSelectionStart < 1) return;--mSelectionEnd;}Insert("");}}#if !MOBILE/// <summary>/// Handle the specified event./// </summary>public virtual bool ProcessEvent (Event ev){if (label == null) return false;RuntimePlatform rp = Application.platform;#if UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2 || UNITY_5_3bool isMac = (rp == RuntimePlatform.OSXEditor ||rp == RuntimePlatform.OSXPlayer ||rp == RuntimePlatform.OSXWebPlayer);#elsebool isMac = (rp == RuntimePlatform.OSXEditor ||rp == RuntimePlatform.OSXPlayer);#endifbool ctrl = isMac ?((ev.modifiers & EventModifiers.Command) != 0) :((ev.modifiers & EventModifiers.Control) != 0);// http://www.tasharen.com/forum/index.php?topic=10780.0if ((ev.modifiers & EventModifiers.Alt) != 0) ctrl = false;bool shift = ((ev.modifiers & EventModifiers.Shift) != 0);switch (ev.keyCode){case KeyCode.Backspace:{ev.Use();DoBackspace();return true;}case KeyCode.Delete:{ev.Use();if (!string.IsNullOrEmpty(mValue)){if (mSelectionStart == mSelectionEnd){if (mSelectionStart >= mValue.Length) return true;++mSelectionEnd;}Insert("");}return true;}case KeyCode.LeftArrow:{ev.Use();if (!string.IsNullOrEmpty(mValue)){mSelectionEnd = Mathf.Max(mSelectionEnd - 1, 0);if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}case KeyCode.RightArrow:{ev.Use();if (!string.IsNullOrEmpty(mValue)){mSelectionEnd = Mathf.Min(mSelectionEnd + 1, mValue.Length);if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}case KeyCode.PageUp:{ev.Use();if (!string.IsNullOrEmpty(mValue)){mSelectionEnd = 0;if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}case KeyCode.PageDown:{ev.Use();if (!string.IsNullOrEmpty(mValue)){mSelectionEnd = mValue.Length;if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}case KeyCode.Home:{ev.Use();if (!string.IsNullOrEmpty(mValue)){if (label.multiLine){mSelectionEnd = label.GetCharacterIndex(mSelectionEnd, KeyCode.Home);}else mSelectionEnd = 0;if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}case KeyCode.End:{ev.Use();if (!string.IsNullOrEmpty(mValue)){if (label.multiLine){mSelectionEnd = label.GetCharacterIndex(mSelectionEnd, KeyCode.End);}else mSelectionEnd = mValue.Length;if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}case KeyCode.UpArrow:{ev.Use();if (!string.IsNullOrEmpty(mValue)){mSelectionEnd = label.GetCharacterIndex(mSelectionEnd, KeyCode.UpArrow);if (mSelectionEnd != 0) mSelectionEnd += mDrawStart;if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}case KeyCode.DownArrow:{ev.Use();if (!string.IsNullOrEmpty(mValue)){mSelectionEnd = label.GetCharacterIndex(mSelectionEnd, KeyCode.DownArrow);if (mSelectionEnd != label.processedText.Length) mSelectionEnd += mDrawStart;else mSelectionEnd = mValue.Length;if (!shift) mSelectionStart = mSelectionEnd;UpdateLabel();}return true;}// Select allcase KeyCode.A:{if (ctrl){ev.Use();mSelectionStart = 0;mSelectionEnd = mValue.Length;UpdateLabel();}return true;}// Copycase KeyCode.C:{if (ctrl){ev.Use();NGUITools.clipboard = GetSelection();}return true;}// Pastecase KeyCode.V:{if (ctrl){ev.Use();Insert(NGUITools.clipboard);}return true;}// Cutcase KeyCode.X:{if (ctrl){ev.Use();NGUITools.clipboard = GetSelection();Insert("");}return true;}}return false;}#endif/// <summary>/// Insert the specified text string into the current input value, respecting selection and validation./// </summary>protected virtual void Insert (string text){string left = GetLeftText();string right = GetRightText();int rl = right.Length;StringBuilder sb = new StringBuilder(left.Length + right.Length + text.Length);sb.Append(left);// Append the new textfor (int i = 0, imax = text.Length; i < imax; ++i){// If we have an input validator, validate the input firstchar c = text[i];if (c == '\b'){DoBackspace();continue;}// Can't go past the character limitif (characterLimit > 0 && sb.Length + rl >= characterLimit) break;if (onValidate != null) c = onValidate(sb.ToString(), sb.Length, c);else if (validation != Validation.None) c = Validate(sb.ToString(), sb.Length, c);// Append the character if it hasn't been invalidatedif (c != 0) sb.Append(c);}// Advance the selectionmSelectionStart = sb.Length;mSelectionEnd = mSelectionStart;// Append the text that follows it, ensuring that it's also validated after the inserted valuefor (int i = 0, imax = right.Length; i < imax; ++i){char c = right[i];if (onValidate != null) c = onValidate(sb.ToString(), sb.Length, c);else if (validation != Validation.None) c = Validate(sb.ToString(), sb.Length, c);if (c != 0) sb.Append(c);}mValue = sb.ToString();UpdateLabel();ExecuteOnChange();}/// <summary>/// Get the text to the left of the selection./// </summary>protected string GetLeftText (){int min = Mathf.Min(mSelectionStart, mSelectionEnd, mValue.Length);return (string.IsNullOrEmpty(mValue) || min < 0) ? "" : mValue.Substring(0, min);}/// <summary>/// Get the text to the right of the selection./// </summary>protected string GetRightText (){int max = Mathf.Max(mSelectionStart, mSelectionEnd);//add by cjp//return (string.IsNullOrEmpty(mValue) || max >= mValue.Length) ? "" : mValue.Substring(max);string v = label.text;return (string.IsNullOrEmpty(v) || max >= v.Length) ? "" : v.Substring(max);//add by cjp}/// <summary>/// Get currently selected text./// </summary>protected string GetSelection (){if (string.IsNullOrEmpty(mValue) || mSelectionStart == mSelectionEnd){return "";}else{int min = Mathf.Min(mSelectionStart, mSelectionEnd);int max = Mathf.Max(mSelectionStart, mSelectionEnd);//add by cjpmin = Mathf.Min(min, mValue.Length);max = Mathf.Min(max, mValue.Length);//add by cjpreturn mValue.Substring(min, max - min);}}/// <summary>/// Helper function that retrieves the index of the character under the mouse./// </summary>protected int GetCharUnderMouse (){Vector3[] corners = label.worldCorners;Ray ray = UICamera.currentRay;Plane p = new Plane(corners[0], corners[1], corners[2]);float dist;return p.Raycast(ray, out dist) ? mDrawStart + label.GetCharacterIndexAtPosition(ray.GetPoint(dist), false) : 0;}/// <summary>/// Move the caret on press./// </summary>protected virtual void OnPress (bool isPressed){if (isPressed && isSelected && label != null &&(UICamera.currentScheme == UICamera.ControlScheme.Mouse || UICamera.currentScheme == UICamera.ControlScheme.Touch)){#if !UNITY_EDITOR && (UNITY_WP8 || UNITY_WP_8_1)if (mKeyboard != null) mKeyboard.active = true;#endifselectionEnd = GetCharUnderMouse();if (!Input.GetKey(KeyCode.LeftShift) &&!Input.GetKey(KeyCode.RightShift)) selectionStart = mSelectionEnd;}}/// <summary>/// Drag selection./// </summary>protected virtual void OnDrag (Vector2 delta){if (label != null &&(UICamera.currentScheme == UICamera.ControlScheme.Mouse || UICamera.currentScheme == UICamera.ControlScheme.Touch)){selectionEnd = GetCharUnderMouse();}}/// <summary>/// Ensure we've released the dynamically created resources./// </summary>void OnDisable () { Cleanup(); }/// <summary>/// Cleanup./// </summary>protected virtual void Cleanup (){if (mHighlight) mHighlight.enabled = false;if (mCaret) mCaret.enabled = false;if (mBlankTex){NGUITools.Destroy(mBlankTex);mBlankTex = null;}}/// <summary>/// Submit the input field's text./// </summary>public void Submit (){if (NGUITools.GetActive(this)){mValue = value;if (current == null){current = this;EventDelegate.Execute(onSubmit);current = null;}SaveToPlayerPrefs(mValue);}}/// <summary>/// Update the visual text label./// </summary>public void UpdateLabel (){if (label != null){if (mDoInit) Init();bool selected = isSelected;string fullText = value;bool isEmpty = string.IsNullOrEmpty(fullText) && string.IsNullOrEmpty(Input.compositionString);label.color = (isEmpty && !selected) ? mDefaultColor : activeTextColor;string processed;if (isEmpty){processed = selected ? "" : mDefaultText;label.alignment = mAlignment;}else{if (inputType == InputType.Password){processed = "";string asterisk = "*";if (label.bitmapFont != null && label.bitmapFont.bmFont != null &&label.bitmapFont.bmFont.GetGlyph('*') == null) asterisk = "x";for (int i = 0, imax = fullText.Length; i < imax; ++i) processed += asterisk;}else processed = fullText;// Start with text leading up to the selection//add by cjp// int selPos = selected ? Mathf.Min(processed.Length, cursorPosition) : 0;int selPos = selected ? Mathf.Min(processed.Length, mSelectionStart) : 0;//add by cjpstring left = processed.Substring(0, selPos);// Append the composition string and the cursor characterif (selected) left += Input.compositionString;// Append the text from the selection onwardsprocessed = left + processed.Substring(selPos, processed.Length - selPos);// Clamped content needs to be adjusted furtherif (selected && label.overflowMethod == UILabel.Overflow.ClampContent && label.maxLineCount == 1){// Determine what will actually fit into the given lineint offset = label.CalculateOffsetToFit(processed);if (offset == 0){mDrawStart = 0;label.alignment = mAlignment;}else if (selPos < mDrawStart){mDrawStart = selPos;label.alignment = NGUIText.Alignment.Left;}else if (offset < mDrawStart){mDrawStart = offset;label.alignment = NGUIText.Alignment.Left;}else{offset = label.CalculateOffsetToFit(processed.Substring(0, selPos));if (offset > mDrawStart){mDrawStart = offset;label.alignment = NGUIText.Alignment.Right;}}// If necessary, trim the frontif (mDrawStart != 0)processed = processed.Substring(mDrawStart, processed.Length - mDrawStart);}else{mDrawStart = 0;label.alignment = mAlignment;}}label.text = processed;#if MOBILEif (selected && (mKeyboard == null || inputShouldBeHidden))#elseif (selected)#endif{int start = mSelectionStart - mDrawStart;int end = mSelectionEnd - mDrawStart;// Blank texture used by selection and caretif (mBlankTex == null){mBlankTex = new Texture2D(2, 2, TextureFormat.ARGB32, false);for (int y = 0; y < 2; ++y)for (int x = 0; x < 2; ++x)mBlankTex.SetPixel(x, y, Color.white);mBlankTex.Apply();}// Create the selection highlightif (start != end){if (mHighlight == null){mHighlight = NGUITools.AddWidget<UITexture>(label.cachedGameObject);mHighlight.name = "Input Highlight";mHighlight.mainTexture = mBlankTex;mHighlight.fillGeometry = false;mHighlight.pivot = label.pivot;mHighlight.SetAnchor(label.cachedTransform);}else{mHighlight.pivot = label.pivot;mHighlight.mainTexture = mBlankTex;mHighlight.MarkAsChanged();mHighlight.enabled = true;}}// Create the carterif (mCaret == null){mCaret = NGUITools.AddWidget<UITexture>(label.cachedGameObject);mCaret.name = "Input Caret";mCaret.mainTexture = mBlankTex;mCaret.fillGeometry = false;mCaret.pivot = label.pivot;mCaret.SetAnchor(label.cachedTransform);}else{mCaret.pivot = label.pivot;mCaret.mainTexture = mBlankTex;mCaret.MarkAsChanged();mCaret.enabled = true;}if (start != end){label.PrintOverlay(start, end, mCaret.geometry, mHighlight.geometry, caretColor, selectionColor);mHighlight.enabled = mHighlight.geometry.hasVertices;}else{label.PrintOverlay(start, end, mCaret.geometry, null, caretColor, selectionColor);if (mHighlight != null) mHighlight.enabled = false;}// Reset the blinking timemNextBlink = RealTime.time + 0.5f;mLastAlpha = label.finalAlpha;}else Cleanup();}}/// <summary>/// Validate the specified input./// </summary>protected char Validate (string text, int pos, char ch){// Validation is disabledif (validation == Validation.None || !enabled) return ch;if (validation == Validation.Integer){// Integer number validationif (ch >= '0' && ch <= '9') return ch;if (ch == '-' && pos == 0 && !text.Contains("-")) return ch;}else if (validation == Validation.Float){// Floating-point numberif (ch >= '0' && ch <= '9') return ch;if (ch == '-' && pos == 0 && !text.Contains("-")) return ch;if (ch == '.' && !text.Contains(".")) return ch;}else if (validation == Validation.Alphanumeric){// All alphanumeric charactersif (ch >= 'A' && ch <= 'Z') return ch;if (ch >= 'a' && ch <= 'z') return ch;if (ch >= '0' && ch <= '9') return ch;}else if (validation == Validation.Username){// Lowercase and numbersif (ch >= 'A' && ch <= 'Z') return (char)(ch - 'A' + 'a');if (ch >= 'a' && ch <= 'z') return ch;if (ch >= '0' && ch <= '9') return ch;}else if (validation == Validation.Filename){if (ch == ':') return (char)0;if (ch == '/') return (char)0;if (ch == '\\') return (char)0;if (ch == '<') return (char)0;if (ch == '>') return (char)0;if (ch == '|') return (char)0;if (ch == '^') return (char)0;if (ch == '*') return (char)0;if (ch == ';') return (char)0;if (ch == '"') return (char)0;if (ch == '`') return (char)0;if (ch == '\t') return (char)0;if (ch == '\n') return (char)0;return ch;}else if (validation == Validation.Name){char lastChar = (text.Length > 0) ? text[Mathf.Clamp(pos, 0, text.Length - 1)] : ' ';char nextChar = (text.Length > 0) ? text[Mathf.Clamp(pos + 1, 0, text.Length - 1)] : '\n';if (ch >= 'a' && ch <= 'z'){// Space followed by a letter -- make sure it's capitalizedif (lastChar == ' ') return (char)(ch - 'a' + 'A');return ch;}else if (ch >= 'A' && ch <= 'Z'){// Uppercase letters are only allowed after spaces (and apostrophes)if (lastChar != ' ' && lastChar != '\'') return (char)(ch - 'A' + 'a');return ch;}else if (ch == '\''){// Don't allow more than one apostropheif (lastChar != ' ' && lastChar != '\'' && nextChar != '\'' && !text.Contains("'")) return ch;}else if (ch == ' '){// Don't allow more than one space in a rowif (lastChar != ' ' && lastChar != '\'' && nextChar != ' ' && nextChar != '\'') return ch;}}return (char)0;}/// <summary>/// Execute the OnChange callback./// </summary>protected void ExecuteOnChange (){if (current == null && EventDelegate.IsValid(onChange)){current = this;EventDelegate.Execute(onChange);current = null;}}/// <summary>/// Convenience function to be used as a callback that will clear the input field's focus./// </summary>public void RemoveFocus () { isSelected = false; }/// <summary>/// Convenience function that can be used as a callback for On Change notification./// </summary>public void SaveValue () { SaveToPlayerPrefs(mValue); }/// <summary>/// Convenience function that can forcefully reset the input field's value to what was saved earlier./// </summary>public void LoadValue (){if (!string.IsNullOrEmpty(savedAs)){string val = mValue.Replace("\\n", "\n");mValue = "";value = PlayerPrefs.HasKey(savedAs) ? PlayerPrefs.GetString(savedAs) : val;}}}


原创粉丝点击