Squashes 146 commits from battle-engine-extraction. Net: 2,045 files changed, +11,896 / -158,687 lines. Ships engine passes 4-7 (dead-code cull, view-layer stub, receive-path shrink) plus the Phase-5 AsyncLocal ambient deletion that turns concurrent battles into a type-system property rather than a scope contract. ## What landed **Passes 4-7 (chunks 1-34):** Extended the Phase-4 const-false collapse into a cascading cull across the skill graph, view layer, and receive-path periphery. Six mode flags (IsWatchBattle/IsReplayBattle/IsAdmin/IsAdminWatch/IsPuzzleQuest/ IsAINetwork) became `const false`, every guarded block deleted. Field*.cs subclass ctors + BackGroundBase + ObjectChecker culled to no-ops. Mulligan family reworked to take a mgr param through IMulliganMgr.InitMulligan. Emotion/Recovery/Resource clusters null-stubbed. Prediction/OperationSimulator/ skill filters converted from static ambient reads to per-mgr reads via SkillPrm.ownerCard.SelfBattlePlayer.BattleMgr / ins.BattleMgr / this.BattleMgr. **Phase-5 ambient rip (chunks 35-47):** Deleted BattleAmbient / BattleAmbient- Context / TestBattleScope in full. Every per-battle mutable slot now lives on the mgr instance itself: mgr.InstanceIsForecast / InstanceIsRandomDraw / InstanceRecoveryInfo / InstanceViewerId / InstanceNetworkAgent / GameMgr BattleManagerBase.GetIns() returns null unconditionally; the residual static flags + 3 façades (Certification.ViewerId, Data.BattleRecoveryInfo, ToolboxGame.RealTimeNetworkAgent) are null-tolerant defaults kept for the handful of engine-internal readers that still reference their types. Zero BattleAmbient references anywhere in engine + node + tests. Added pre-seeded GameMgr ctor overload threaded through the mgr chain (BattleManagerBase → SingleBattleMgr / NetworkBattleManagerBase → NetworkStandard- BattleMgr → HeadlessBattleMgr / HeadlessNetworkBattleMgr). Fixtures build a GameMgr, seed it via HeadlessEngineEnv.SeedCharaIds/SeedNetUser, and pass it to the mgr's ctor — no ambient reach. Node side (SVSim.BattleNode/SessionBattleEngine): _ctx replaced with a plain GameMgr field; 34 `using var _ambient = BattleAmbient.Enter(_ctx)` scope wraps ripped from every accessor and mutator; EngineGlobalInit.WirePerSessionGameMgr takes GameMgr as a param and runs from SessionBattleEngine.SetupInternal BEFORE mgr construction. Test side: TestBattleScope deleted; 18 fixture [SetUp]s migrated to `HeadlessEngineEnv.EnsureProcessGlobals()`; MultiInstanceEngineTests rewritten around per-mgr construction (GetIns() → null is the pinned invariant). ## Regression fixes - **chunk-48** (MulliganCtrl): chunk-35's `= null` stubs on card lookups broke the live receive-driven Deal path (BattlePlayerBase.DrawCard NRE'd downstream of NetworkPlayerMulliganCtrl.StartMulliganVfx). Restored the three lookups via `_battlePlayer.BattleMgr.GetBattleCardIdx`. Engine tests were satisfied by the WireMulliganPhase seam; unit tests exposed the live-path gap. ## Ship state - SVSim.BattleEngine.Tests: 56/56 pass, 2 skip - SVSim.UnitTests: 1554/1554 pass (was 1523/31-fail before chunk 48) - Solution build: 0 source warnings (40 pre-existing NU1902 MessagePack CVEs in SVSim.EmulatedEntrypoint, unrelated) - Sequential PVP smoke: verified live (two back-to-back battles, no regression on cleanup/spinup) - Concurrent PVP smoke: verified live Adds tools/engine-port/ClosureAnalyzer/ — the Roslyn transitive-type-closure analyzer needed to make future cascade cleanup safe (per feedback memory "Engine cleanup needs closure tool" from the 2026-06-28 pass-3 failure). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1030 lines
22 KiB
C#
1030 lines
22 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using UnityEngine;
|
|
|
|
[AddComponentMenu("NGUI/UI/Input Field")]
|
|
public class UIInput : MonoBehaviour
|
|
{
|
|
public enum InputType
|
|
{
|
|
Password
|
|
}
|
|
|
|
public enum Validation
|
|
{
|
|
None,
|
|
Integer,
|
|
Float,
|
|
Alphanumeric,
|
|
Username,
|
|
Name,
|
|
Filename
|
|
}
|
|
|
|
public enum KeyboardType
|
|
{
|
|
Default }
|
|
|
|
public enum OnReturnKey
|
|
{
|
|
Default,
|
|
NewLine
|
|
}
|
|
|
|
public delegate char OnValidate(string text, int charIndex, char addedChar);
|
|
|
|
private bool isAfterPaste;
|
|
|
|
public static UIInput current;
|
|
|
|
public static UIInput selection;
|
|
|
|
public UILabel label;
|
|
|
|
public InputType inputType;
|
|
|
|
public OnReturnKey onReturnKey;
|
|
|
|
public KeyboardType keyboardType;
|
|
|
|
[NonSerialized]
|
|
public bool selectAllTextOnFocus = true;
|
|
|
|
public Validation validation;
|
|
|
|
public int characterLimit;
|
|
|
|
public string savedAs;
|
|
|
|
public Color activeTextColor = Color.white;
|
|
|
|
public Color caretColor = new Color(1f, 1f, 1f, 0.8f);
|
|
|
|
public Color selectionColor = new Color(1f, 0.8745098f, 47f / 85f, 0.5f);
|
|
|
|
public List<EventDelegate> onSubmit = new List<EventDelegate>();
|
|
|
|
public List<EventDelegate> onChange = new List<EventDelegate>();
|
|
|
|
public OnValidate onValidate;
|
|
|
|
[SerializeField]
|
|
[HideInInspector]
|
|
protected string mValue;
|
|
|
|
[NonSerialized]
|
|
protected string mDefaultText = "";
|
|
|
|
[NonSerialized]
|
|
protected Color mDefaultColor = Color.white;
|
|
|
|
[NonSerialized]
|
|
protected float mPosition;
|
|
|
|
[NonSerialized]
|
|
protected bool mDoInit = true;
|
|
|
|
[NonSerialized]
|
|
protected NGUIText.Alignment mAlignment = NGUIText.Alignment.Left;
|
|
|
|
[NonSerialized]
|
|
protected bool mLoadSavedValue = true;
|
|
|
|
protected string _imeString = "";
|
|
|
|
private bool _wasComposingBeforeDeselection;
|
|
|
|
protected static int mDrawStart = 0;
|
|
|
|
protected static string mLastIME = "";
|
|
|
|
[NonSerialized]
|
|
protected int mSelectionStart;
|
|
|
|
[NonSerialized]
|
|
protected int mSelectionEnd;
|
|
|
|
[NonSerialized]
|
|
protected UITexture mHighlight;
|
|
|
|
[NonSerialized]
|
|
protected UITexture mCaret;
|
|
|
|
[NonSerialized]
|
|
protected Texture2D mBlankTex;
|
|
|
|
[NonSerialized]
|
|
protected float mNextBlink;
|
|
|
|
[NonSerialized]
|
|
protected float mLastAlpha;
|
|
|
|
[NonSerialized]
|
|
protected int mSelectMe = -1;
|
|
|
|
[NonSerialized]
|
|
protected int mSelectTime = -1;
|
|
|
|
[NonSerialized]
|
|
private UIInputOnGUI mOnGUI;
|
|
|
|
[NonSerialized]
|
|
private UICamera mCam;
|
|
|
|
[NonSerialized]
|
|
private bool mEllipsis;
|
|
|
|
private static int mIgnoreKey = 0;
|
|
|
|
public string value
|
|
{
|
|
get
|
|
{
|
|
if (mDoInit)
|
|
{
|
|
Init();
|
|
}
|
|
return mValue;
|
|
}
|
|
set
|
|
{
|
|
if (mDoInit)
|
|
{
|
|
Init();
|
|
}
|
|
mDrawStart = 0;
|
|
if (Application.platform == RuntimePlatform.BlackBerryPlayer)
|
|
{
|
|
value = value.Replace("\\b", "\b");
|
|
}
|
|
value = Validate(value);
|
|
if (!(mValue != value))
|
|
{
|
|
return;
|
|
}
|
|
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();
|
|
}
|
|
}
|
|
|
|
public bool isSelected
|
|
{
|
|
get
|
|
{
|
|
return selection == this;
|
|
}
|
|
set
|
|
{
|
|
if (!value)
|
|
{
|
|
if (isSelected)
|
|
{
|
|
UICamera.selectedObject = null;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UICamera.selectedObject = base.gameObject;
|
|
}
|
|
}
|
|
}
|
|
|
|
public int cursorPosition
|
|
{
|
|
get
|
|
{
|
|
if (!isSelected)
|
|
{
|
|
return value.Length;
|
|
}
|
|
return mSelectionEnd;
|
|
}
|
|
set
|
|
{
|
|
if (isSelected)
|
|
{
|
|
mSelectionEnd = value;
|
|
UpdateLabel();
|
|
}
|
|
}
|
|
}
|
|
|
|
public int selectionStart
|
|
{
|
|
get
|
|
{
|
|
if (!isSelected)
|
|
{
|
|
return value.Length;
|
|
}
|
|
return mSelectionStart;
|
|
}
|
|
set
|
|
{
|
|
if (isSelected)
|
|
{
|
|
mSelectionStart = value;
|
|
UpdateLabel(dontAddCompositionString: true);
|
|
}
|
|
}
|
|
}
|
|
|
|
public int selectionEnd
|
|
{
|
|
get
|
|
{
|
|
if (!isSelected)
|
|
{
|
|
return value.Length;
|
|
}
|
|
return mSelectionEnd;
|
|
}
|
|
set
|
|
{
|
|
if (isSelected)
|
|
{
|
|
mSelectionEnd = value;
|
|
UpdateLabel(dontAddCompositionString: true);
|
|
}
|
|
}
|
|
}
|
|
|
|
public string Validate(string val)
|
|
{
|
|
if (string.IsNullOrEmpty(val))
|
|
{
|
|
return "";
|
|
}
|
|
StringBuilder stringBuilder = new StringBuilder(val.Length);
|
|
for (int i = 0; i < val.Length; i++)
|
|
{
|
|
char c = val[i];
|
|
if (onValidate != null)
|
|
{
|
|
c = onValidate(stringBuilder.ToString(), stringBuilder.Length, c);
|
|
}
|
|
else if (validation != Validation.None)
|
|
{
|
|
c = Validate(stringBuilder.ToString(), stringBuilder.Length, c);
|
|
}
|
|
if (c != 0)
|
|
{
|
|
stringBuilder.Append(c);
|
|
}
|
|
}
|
|
if (characterLimit > 0 && stringBuilder.Length > characterLimit)
|
|
{
|
|
return stringBuilder.ToString(0, characterLimit);
|
|
}
|
|
return stringBuilder.ToString();
|
|
}
|
|
|
|
protected void Init()
|
|
{
|
|
if (mDoInit && label != null)
|
|
{
|
|
mDoInit = false;
|
|
mDefaultText = label.text;
|
|
mDefaultColor = label.color;
|
|
label.supportEncoding = false;
|
|
mEllipsis = label.overflowEllipsis;
|
|
if (label.alignment == NGUIText.Alignment.Justified)
|
|
{
|
|
label.alignment = NGUIText.Alignment.Left;
|
|
}
|
|
mAlignment = label.alignment;
|
|
mPosition = label.cachedTransform.localPosition.x;
|
|
UpdateLabel();
|
|
}
|
|
}
|
|
|
|
protected void SaveToPlayerPrefs(string val)
|
|
{
|
|
if (!string.IsNullOrEmpty(savedAs))
|
|
{
|
|
if (string.IsNullOrEmpty(val))
|
|
{
|
|
PlayerPrefs.DeleteKey(savedAs);
|
|
}
|
|
else
|
|
{
|
|
PlayerPrefs.SetString(savedAs, val);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected virtual void OnSelect(bool isSelected)
|
|
{
|
|
if (isSelected)
|
|
{
|
|
if (mOnGUI == null)
|
|
{
|
|
mOnGUI = base.gameObject.AddComponent<UIInputOnGUI>();
|
|
}
|
|
OnSelectEvent();
|
|
return;
|
|
}
|
|
if (mOnGUI != null)
|
|
{
|
|
UnityEngine.Object.Destroy(mOnGUI);
|
|
mOnGUI = null;
|
|
}
|
|
OnDeselectEvent();
|
|
}
|
|
|
|
protected virtual void OnSelectEvent()
|
|
{
|
|
mSelectTime = Time.frameCount;
|
|
selection = this;
|
|
if (mDoInit)
|
|
{
|
|
Init();
|
|
}
|
|
if (label != null)
|
|
{
|
|
mEllipsis = label.overflowEllipsis;
|
|
label.overflowEllipsis = false;
|
|
}
|
|
if (label != null && NGUITools.GetActive(this) && !_wasComposingBeforeDeselection)
|
|
{
|
|
mSelectMe = Time.frameCount;
|
|
}
|
|
if (_wasComposingBeforeDeselection)
|
|
{
|
|
_wasComposingBeforeDeselection = false;
|
|
}
|
|
}
|
|
|
|
protected virtual void OnDeselectEvent()
|
|
{
|
|
if (mDoInit)
|
|
{
|
|
Init();
|
|
}
|
|
if (label != null)
|
|
{
|
|
label.overflowEllipsis = mEllipsis;
|
|
}
|
|
if (label != null && NGUITools.GetActive(this))
|
|
{
|
|
mValue = value;
|
|
if (!string.IsNullOrEmpty(_imeString))
|
|
{
|
|
UpdateFromInput(_imeString, "");
|
|
_wasComposingBeforeDeselection = true;
|
|
selection = null;
|
|
return;
|
|
}
|
|
if (string.IsNullOrEmpty(mValue))
|
|
{
|
|
label.text = mDefaultText;
|
|
label.color = mDefaultColor;
|
|
}
|
|
else
|
|
{
|
|
label.text = mValue;
|
|
}
|
|
Input.imeCompositionMode = IMECompositionMode.Auto;
|
|
label.alignment = mAlignment;
|
|
}
|
|
selection = null;
|
|
UpdateLabel();
|
|
}
|
|
|
|
protected virtual void Update()
|
|
{
|
|
if (!isSelected || mSelectTime == Time.frameCount)
|
|
{
|
|
return;
|
|
}
|
|
if (mDoInit)
|
|
{
|
|
Init();
|
|
}
|
|
if (_wasComposingBeforeDeselection)
|
|
{
|
|
_imeString = null;
|
|
mSelectMe = -1;
|
|
return;
|
|
}
|
|
if (mSelectMe != -1 && mSelectMe != Time.frameCount)
|
|
{
|
|
mSelectMe = -1;
|
|
mSelectionEnd = ((!string.IsNullOrEmpty(mValue)) ? mValue.Length : 0);
|
|
mDrawStart = 0;
|
|
mSelectionStart = ((!selectAllTextOnFocus) ? mSelectionEnd : 0);
|
|
label.color = activeTextColor;
|
|
Vector2 compositionCursorPos = ((UICamera.current != null && UICamera.current.cachedCamera != null) ? UICamera.current.cachedCamera.WorldToScreenPoint(label.worldCorners[0]) : label.worldCorners[0]);
|
|
compositionCursorPos.y = (float)Screen.height - compositionCursorPos.y;
|
|
Input.imeCompositionMode = IMECompositionMode.On;
|
|
Input.compositionCursorPos = compositionCursorPos;
|
|
UpdateLabel();
|
|
if (string.IsNullOrEmpty(Input.inputString))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
bool flag = false;
|
|
if (!string.IsNullOrEmpty(Input.inputString) && Input.inputString != "\n" && !string.IsNullOrEmpty(Input.compositionString))
|
|
{
|
|
UpdateFromInput(Input.inputString, "");
|
|
}
|
|
flag |= UpdateFromInput(Input.inputString, Input.compositionString);
|
|
if (mCaret != null && mNextBlink < RealTime.time)
|
|
{
|
|
mNextBlink = RealTime.time + 0.5f;
|
|
mCaret.enabled = !mCaret.enabled;
|
|
}
|
|
if (isSelected && mLastAlpha != label.finalAlpha)
|
|
{
|
|
UpdateLabel();
|
|
}
|
|
if (mCam == null)
|
|
{
|
|
mCam = UICamera.FindCameraForLayer(base.gameObject.layer);
|
|
}
|
|
if (!(mCam != null))
|
|
{
|
|
return;
|
|
}
|
|
if (UICamera.GetKeyDown(mCam.submitKey0))
|
|
{
|
|
if ((onReturnKey == OnReturnKey.NewLine && !flag) || (onReturnKey == OnReturnKey.Default && label.multiLine && !Input.GetKey(KeyCode.LeftControl) && !Input.GetKey(KeyCode.RightControl) && label.overflowMethod != UILabel.Overflow.ClampContent && validation == Validation.None))
|
|
{
|
|
Insert("\n");
|
|
}
|
|
else
|
|
{
|
|
if (UICamera.controller.current != null)
|
|
{
|
|
UICamera.controller.clickNotification = UICamera.ClickNotification.None;
|
|
}
|
|
UICamera.currentKey = mCam.submitKey0;
|
|
Submit();
|
|
}
|
|
}
|
|
if (UICamera.GetKeyDown(mCam.submitKey1))
|
|
{
|
|
if (onReturnKey == OnReturnKey.NewLine || (onReturnKey == OnReturnKey.Default && label.multiLine && !Input.GetKey(KeyCode.LeftControl) && !Input.GetKey(KeyCode.RightControl) && label.overflowMethod != UILabel.Overflow.ClampContent && validation == Validation.None))
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
private void OnKey(KeyCode key)
|
|
{
|
|
int frameCount = Time.frameCount;
|
|
if (mIgnoreKey == frameCount)
|
|
{
|
|
return;
|
|
}
|
|
if (mCam != null && (key == mCam.cancelKey0 || key == mCam.cancelKey1))
|
|
{
|
|
mIgnoreKey = frameCount;
|
|
isSelected = false;
|
|
}
|
|
else if (key == KeyCode.Tab)
|
|
{
|
|
mIgnoreKey = frameCount;
|
|
isSelected = false;
|
|
UIKeyNavigation component = GetComponent<UIKeyNavigation>();
|
|
if (component != null)
|
|
{
|
|
component.OnKey(KeyCode.Tab);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void DoBackspace()
|
|
{
|
|
if (string.IsNullOrEmpty(mValue))
|
|
{
|
|
return;
|
|
}
|
|
if (mSelectionStart == mSelectionEnd)
|
|
{
|
|
if (mSelectionStart < 1)
|
|
{
|
|
return;
|
|
}
|
|
mSelectionEnd--;
|
|
}
|
|
Insert("");
|
|
}
|
|
|
|
protected virtual void Insert(string text, bool dontAddCompositionString = false)
|
|
{
|
|
string leftText = GetLeftText();
|
|
string rightText = GetRightText();
|
|
int length = rightText.Length;
|
|
StringBuilder stringBuilder = new StringBuilder(leftText.Length + rightText.Length + text.Length);
|
|
stringBuilder.Append(leftText);
|
|
int i = 0;
|
|
for (int length2 = text.Length; i < length2; i++)
|
|
{
|
|
char c = text[i];
|
|
if (c == '\b')
|
|
{
|
|
DoBackspace();
|
|
continue;
|
|
}
|
|
if (characterLimit > 0 && stringBuilder.Length + length >= characterLimit)
|
|
{
|
|
break;
|
|
}
|
|
if (onValidate != null)
|
|
{
|
|
c = onValidate(stringBuilder.ToString(), stringBuilder.Length, c);
|
|
}
|
|
else if (validation != Validation.None)
|
|
{
|
|
c = Validate(stringBuilder.ToString(), stringBuilder.Length, c);
|
|
}
|
|
if (c != 0)
|
|
{
|
|
stringBuilder.Append(c);
|
|
}
|
|
}
|
|
mSelectionStart = stringBuilder.Length;
|
|
mSelectionEnd = mSelectionStart;
|
|
int j = 0;
|
|
for (int length3 = rightText.Length; j < length3; j++)
|
|
{
|
|
char c2 = rightText[j];
|
|
if (onValidate != null)
|
|
{
|
|
c2 = onValidate(stringBuilder.ToString(), stringBuilder.Length, c2);
|
|
}
|
|
else if (validation != Validation.None)
|
|
{
|
|
c2 = Validate(stringBuilder.ToString(), stringBuilder.Length, c2);
|
|
}
|
|
if (c2 != 0)
|
|
{
|
|
stringBuilder.Append(c2);
|
|
}
|
|
}
|
|
mValue = stringBuilder.ToString();
|
|
UpdateLabel(dontAddCompositionString);
|
|
ExecuteOnChange();
|
|
}
|
|
|
|
protected string GetLeftText()
|
|
{
|
|
int num = Mathf.Min(mSelectionStart, mSelectionEnd, mValue.Length);
|
|
if (!string.IsNullOrEmpty(mValue) && num >= 0)
|
|
{
|
|
return mValue.Substring(0, num);
|
|
}
|
|
return "";
|
|
}
|
|
|
|
protected string GetRightText()
|
|
{
|
|
int num = Mathf.Max(mSelectionStart, mSelectionEnd);
|
|
if (!string.IsNullOrEmpty(mValue) && num < mValue.Length)
|
|
{
|
|
return mValue.Substring(num);
|
|
}
|
|
return "";
|
|
}
|
|
|
|
protected int GetCharUnderMouse()
|
|
{
|
|
if (string.IsNullOrEmpty(label.text))
|
|
{
|
|
return 0;
|
|
}
|
|
Vector3[] worldCorners = label.worldCorners;
|
|
Ray currentRay = UICamera.currentRay;
|
|
if (!new Plane(worldCorners[0], worldCorners[1], worldCorners[2]).Raycast(currentRay, out var enter))
|
|
{
|
|
return 0;
|
|
}
|
|
return mDrawStart + label.GetCharacterIndexAtPosition(currentRay.GetPoint(enter), precise: false);
|
|
}
|
|
|
|
protected virtual void OnPress(bool isPressed)
|
|
{
|
|
if (isPressed && isSelected && label != null && string.IsNullOrEmpty(_imeString) && !_wasComposingBeforeDeselection && (UICamera.currentScheme == UICamera.ControlScheme.Mouse || UICamera.currentScheme == UICamera.ControlScheme.Touch))
|
|
{
|
|
selectionEnd = GetCharUnderMouse();
|
|
if (!Input.GetKey(KeyCode.LeftShift) && !Input.GetKey(KeyCode.RightShift))
|
|
{
|
|
selectionStart = mSelectionEnd;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected virtual void Cleanup()
|
|
{
|
|
if ((bool)mHighlight)
|
|
{
|
|
mHighlight.enabled = false;
|
|
}
|
|
if ((bool)mCaret)
|
|
{
|
|
mCaret.enabled = false;
|
|
}
|
|
if ((bool)mBlankTex)
|
|
{
|
|
NGUITools.Destroy(mBlankTex);
|
|
mBlankTex = null;
|
|
}
|
|
}
|
|
|
|
public void Submit()
|
|
{
|
|
if (NGUITools.GetActive(this))
|
|
{
|
|
mValue = value;
|
|
if (current == null)
|
|
{
|
|
current = this;
|
|
EventDelegate.Execute(onSubmit);
|
|
current = null;
|
|
}
|
|
SaveToPlayerPrefs(mValue);
|
|
}
|
|
}
|
|
|
|
public void UpdateLabel(bool dontAddCompositionString = false, bool isIme = false)
|
|
{
|
|
if (!(label != null))
|
|
{
|
|
return;
|
|
}
|
|
if (mDoInit)
|
|
{
|
|
Init();
|
|
}
|
|
bool flag = isSelected;
|
|
string text = value;
|
|
bool flag2 = string.IsNullOrEmpty(text) && string.IsNullOrEmpty(Input.compositionString);
|
|
label.color = ((flag2 && !flag) ? mDefaultColor : activeTextColor);
|
|
string text2;
|
|
if (flag2)
|
|
{
|
|
text2 = (flag ? "" : mDefaultText);
|
|
label.alignment = mAlignment;
|
|
}
|
|
else
|
|
{
|
|
if (inputType == InputType.Password)
|
|
{
|
|
text2 = "";
|
|
string text3 = "*";
|
|
if (label.bitmapFont != null && label.bitmapFont.bmFont != null && label.bitmapFont.bmFont.GetGlyph(42) == null)
|
|
{
|
|
text3 = "x";
|
|
}
|
|
int i = 0;
|
|
for (int length = text.Length; i < length; i++)
|
|
{
|
|
text2 += text3;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
text2 = text;
|
|
}
|
|
int num = (flag ? Mathf.Min(text2.Length, cursorPosition) : 0);
|
|
string text4 = text2.Substring(0, num);
|
|
if (flag && !dontAddCompositionString)
|
|
{
|
|
text4 += Input.compositionString;
|
|
}
|
|
text2 = text4 + text2.Substring(num, text2.Length - num);
|
|
if (flag && label.overflowMethod == UILabel.Overflow.ClampContent && label.maxLineCount == 1)
|
|
{
|
|
int num2 = label.CalculateOffsetToFit(text2);
|
|
if (num2 == 0)
|
|
{
|
|
mDrawStart = 0;
|
|
label.alignment = mAlignment;
|
|
}
|
|
else if (num < mDrawStart)
|
|
{
|
|
mDrawStart = num;
|
|
label.alignment = NGUIText.Alignment.Left;
|
|
}
|
|
else if (num2 < mDrawStart)
|
|
{
|
|
mDrawStart = num2;
|
|
label.alignment = NGUIText.Alignment.Left;
|
|
}
|
|
else
|
|
{
|
|
num2 = label.CalculateOffsetToFit(text2.Substring(0, num));
|
|
if (num2 > mDrawStart)
|
|
{
|
|
mDrawStart = num2;
|
|
label.alignment = NGUIText.Alignment.Right;
|
|
}
|
|
}
|
|
if (mDrawStart != 0)
|
|
{
|
|
text2 = text2.Substring(mDrawStart, text2.Length - mDrawStart);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mDrawStart = 0;
|
|
label.alignment = mAlignment;
|
|
}
|
|
}
|
|
label.text = text2;
|
|
if (flag)
|
|
{
|
|
int num3 = mSelectionStart - mDrawStart;
|
|
int num4 = mSelectionEnd - mDrawStart;
|
|
if (isIme && !string.IsNullOrEmpty(Input.compositionString))
|
|
{
|
|
num4 += Input.compositionString.Length;
|
|
}
|
|
if (mBlankTex == null)
|
|
{
|
|
mBlankTex = new Texture2D(2, 2, TextureFormat.ARGB32, mipChain: false);
|
|
for (int j = 0; j < 2; j++)
|
|
{
|
|
for (int k = 0; k < 2; k++)
|
|
{
|
|
mBlankTex.SetPixel(k, j, Color.white);
|
|
}
|
|
}
|
|
mBlankTex.Apply();
|
|
}
|
|
if (num3 != num4)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
if (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 (num3 != num4)
|
|
{
|
|
label.PrintOverlay(num3, num4, mCaret.geometry, mHighlight.geometry, caretColor, selectionColor);
|
|
mHighlight.enabled = mHighlight.geometry.hasVertices;
|
|
}
|
|
else
|
|
{
|
|
label.PrintOverlay(num3, num4, mCaret.geometry, null, caretColor, selectionColor);
|
|
if (mHighlight != null)
|
|
{
|
|
mHighlight.enabled = false;
|
|
}
|
|
}
|
|
mNextBlink = RealTime.time + 0.5f;
|
|
mLastAlpha = label.finalAlpha;
|
|
}
|
|
else
|
|
{
|
|
Cleanup();
|
|
}
|
|
}
|
|
|
|
protected char Validate(string text, int pos, char ch)
|
|
{
|
|
if (validation == Validation.None || !base.enabled)
|
|
{
|
|
return ch;
|
|
}
|
|
if (validation == Validation.Integer)
|
|
{
|
|
if (ch >= '0' && ch <= '9')
|
|
{
|
|
return ch;
|
|
}
|
|
if (ch == '-' && pos == 0 && !text.Contains("-"))
|
|
{
|
|
return ch;
|
|
}
|
|
}
|
|
else if (validation == Validation.Float)
|
|
{
|
|
if (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)
|
|
{
|
|
if (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)
|
|
{
|
|
if (ch >= 'A' && ch <= 'Z')
|
|
{
|
|
return (char)(ch - 65 + 97);
|
|
}
|
|
if (ch >= 'a' && ch <= 'z')
|
|
{
|
|
return ch;
|
|
}
|
|
if (ch >= '0' && ch <= '9')
|
|
{
|
|
return ch;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (validation == Validation.Filename)
|
|
{
|
|
return ch switch
|
|
{
|
|
':' => '\0',
|
|
'/' => '\0',
|
|
'\\' => '\0',
|
|
'<' => '\0',
|
|
'>' => '\0',
|
|
'|' => '\0',
|
|
'^' => '\0',
|
|
'*' => '\0',
|
|
';' => '\0',
|
|
'"' => '\0',
|
|
'`' => '\0',
|
|
'\t' => '\0',
|
|
'\n' => '\0',
|
|
_ => ch,
|
|
};
|
|
}
|
|
if (validation == Validation.Name)
|
|
{
|
|
char c = ((text.Length > 0) ? text[Mathf.Clamp(pos, 0, text.Length - 1)] : ' ');
|
|
char c2 = ((text.Length > 0) ? text[Mathf.Clamp(pos + 1, 0, text.Length - 1)] : '\n');
|
|
if (ch >= 'a' && ch <= 'z')
|
|
{
|
|
if (c == ' ')
|
|
{
|
|
return (char)(ch - 97 + 65);
|
|
}
|
|
return ch;
|
|
}
|
|
if (ch >= 'A' && ch <= 'Z')
|
|
{
|
|
if (c != ' ' && c != '\'')
|
|
{
|
|
return (char)(ch - 65 + 97);
|
|
}
|
|
return ch;
|
|
}
|
|
switch (ch)
|
|
{
|
|
case '\'':
|
|
if (c != ' ' && c != '\'' && c2 != '\'' && !text.Contains("'"))
|
|
{
|
|
return ch;
|
|
}
|
|
break;
|
|
case ' ':
|
|
if (c != ' ' && c != '\'' && c2 != ' ' && c2 != '\'')
|
|
{
|
|
return ch;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return '\0';
|
|
}
|
|
|
|
protected void ExecuteOnChange()
|
|
{
|
|
if (current == null && EventDelegate.IsValid(onChange))
|
|
{
|
|
current = this;
|
|
EventDelegate.Execute(onChange);
|
|
current = null;
|
|
}
|
|
}
|
|
|
|
public void RemoveFocus()
|
|
{
|
|
isSelected = false;
|
|
}
|
|
|
|
public bool ClearIMEOnlyOSX()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public void ClearFocusOnlyOSX()
|
|
{
|
|
}
|
|
|
|
private bool UpdateFromInput(string inputString, string compositionString, bool forceInsert = false)
|
|
{
|
|
bool result = false;
|
|
if (!string.IsNullOrEmpty(compositionString))
|
|
{
|
|
_imeString = compositionString;
|
|
}
|
|
if ((string.IsNullOrEmpty(compositionString) || forceInsert) && !string.IsNullOrEmpty(inputString) && !isAfterPaste)
|
|
{
|
|
string text = inputString;
|
|
if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1) || Input.GetMouseButtonDown(2))
|
|
{
|
|
text = _imeString;
|
|
}
|
|
_imeString = "";
|
|
for (int i = 0; i < text.Length; i++)
|
|
{
|
|
char c = text[i];
|
|
if (c >= ' ' && c != '\uf700' && c != '\uf701' && c != '\uf702' && c != '\uf703')
|
|
{
|
|
Insert(c.ToString(), forceInsert);
|
|
}
|
|
}
|
|
}
|
|
isAfterPaste = false;
|
|
if (mLastIME != compositionString)
|
|
{
|
|
mLastIME = compositionString;
|
|
UpdateLabel(dontAddCompositionString: false, isIme: true);
|
|
ExecuteOnChange();
|
|
}
|
|
return result;
|
|
}
|
|
}
|