PLAGame.BattleLogicを使用する;
PLAGame.Clientを使用する;
システムを使用する;
System.Collections.Genericを使用する;
System.Textを使用します。
System.Text.RegularExpressionsを使用する;
UnityEngineを使用する;
UnityEngine.Eventsを使用する;
UnityEngine.EventSystemsを使用する;
UnityEngine.UIを使用します。
Newtonsoft.Jsonを使用します。
名前空間UnityEngine.UI
{
/// <summary>
///テキストコントロール、ハイパーリンクのサポート
/// </ summary>
public class HyperlinkText:Text、IPointerDownHandler、IPointerUpHandler、IPointerClickHandler
{ /// <summary> ///ハイパーリンク情報クラス /// </ summary> プライベートクラスHyperlinkInfo { public int startIndex;
public int endIndex;
パブリック文字列名;
public readonly List <Rect> box = new List <Rect>();
}
/// <summary>
///最終テキストを解析した後
/// </ summary>
private string m_OutputText;
/// <summary>
///ハイパーリンク情報リスト
/// </ summary>
プライベート読み取り専用リスト<HyperlinkInfo> m_HrefInfos = new List <HyperlinkInfo>();
/// <summary>
///テキストコンストラクター
/// </ summary>
protected static readonly StringBuilder s_TextBuilder = new StringBuilder();
[Serializable]
public class HrefClickEvent:UnityEvent <string> {}
[SerializeField]
private HrefClickEvent m_OnHrefClick = new HrefClickEvent();
[SerializeField]
private HrefClickEvent m_OnHrefPress = new HrefClickEvent();
/// <summary>
///ハイパーリンククリックイベント
/// </ summary>
public HrefClickEvent onHrefClick
{ get {return m_OnHrefClick;} set {m_OnHrefClick = value;} }
/// <summary>
///ハイパーリンククリックイベント
/// </ summary>
public HrefClickEvent onHrefPress
{ get {return m_OnHrefPress;} set {m_OnHrefPress = value;} }
public UnityEvent PointUpAction;
/// <summary>
///超链接正则
/// </ summary>
private static readonly Regex s_HrefRegex = new Regex(@ "<a href =([^> \ n \ s] +)>(。*? )(</a>) "、RegexOptions.Singleline);
プライベートHyperlinkTextmHyperlinkText;
public string GetHyperlinkInfo
{ get {return text; } } private bool isPointerDown = false; プライベートフロート間隔= 0.3f; プライベートフロートrecordTime; プライベートVector2curlp;
プライベートGameObjectexa;
保護されたオーバーライド voidAwake()
{ base.Awake(); mHyperlinkText = GetComponent <HyperlinkText>();
}
protected override void OnEnable()
{ base.OnEnable(); mHyperlinkText.onHrefClick.AddListener(OnHyperlinkTextInfo); }
保護されたオーバーライドvoidOnDisable()
{ base.OnDisable(); mHyperlinkText.onHrefClick.RemoveListener(OnHyperlinkTextInfo);
}
public override void SetVerticesDirty()
{ base.SetVerticesDirty();
text = GetHyperlinkInfo;
m_OutputText = GetOutputText(text);
}
int getline(IList <UILineInfo> lines、int index)
{ int line = 0;
for(int i = 0; i <lines.Count; i ++)
{ var info = lines [i]; if(index> info.startCharIdx * 4-3) { line = i + 1; } }
リターンライン;
}
保護されたオーバーライドvoidOnPopulateMesh(VertexHelper toFill)
{ var orignText = m_Text; m_Text = m_OutputText; base.OnPopulateMesh(toFill); m_Text = orignText; // print($ "currentVertCount = {toFill.currentVertCount}、currentIndexCount = {toFill.currentIndexCount}"); var lines = cachedTextGeneratorForLayout.lines; varvertexList = new List <UIVertex>(); UIVertex頂点=新しいUIVertex(); int rectCount = toFill.currentVertCount / 4; Dictionary <int、int> afterindexofbeforeindex = new Dictionary <int、int>(); //后来的テクスチャ
//https://www.zhihu.com/question/372690850
//スペースブレークも頂点としてカウントされ、それらの座標は同じであるため
、(int i = 0; i <rectCount; i ++)
{ int startIndex = i *のために削除します。4; toFill.PopulateUIVertex(参照頂点、startIndex); var p1 =頂点; toFill.PopulateUIVertex(参照頂点、startIndex + 1); var p2 =頂点; toFill.PopulateUIVertex(参照頂点、startIndex + 2); var p3 =頂点; toFill.PopulateUIVertex(refvertex、startIndex + 3); var p4 =頂点;
if(p1.position!= p2.position &&
p2.position!= p3.position &&
p3.position!= p4.position)
{ afterindexofbeforeindex.Add(vertexList.Count、startIndex); afterindexofbeforeindex.Add(vertexList.Count + 1、startIndex + 1); afterindexofbeforeindex.Add(vertexList.Count + 2、startIndex + 2); afterindexofbeforeindex.Add(vertexList.Count + 3、startIndex + 3); VertexList.AddRange(new UIVertex [] {p1、p2、p3、p4}); }
}
// Debug.Log($ "最適化前{toFill.currentVertCount}、最適化後{vertexList.Count}");
//行間折り返しの問題は解決されません
//ハイパーリンク境界ボックスを処理します
Dictionary <int、List <Rect >> dicRect = new Dictionary <int、List <Rect >>();
foreach(var hrefInfo in m_HrefInfos)
{
hrefInfo.boxes.Clear();
dicRect.Clear();
// print($ "startIndex = {hrefInfo.startIndex}");
// int line = 1;
//ハイパーリンクにテキスト頂点インデックス座標を追加しますRectには、テキストごとに4つの頂点があります
(int i = hrefInfo.startIndex、m = hrefInfo.endIndex; i <m; i + = 4)
{ if(i> = VertexList.Count)//表示されている部分のみがそれを超えて表示されます表示領域はBreak { break; } int line = getline(lines、afterindexofbeforeindex [i]); //行数を取得する 必要があり ますRectrect = new Rect(); UIVertex vert1 = VertexList [i];
UIVertex vert3 = VertexList [i + 2];
rect.width = Math.Abs(vert1.position.x --vert3.position.x);
rect.height = Math.Abs(vert1.position.y --vert3.position.y);
rect.x =(vert1.position.x + vert3.position.x)/ 2;
rect.y =(vert1.position.y + vert3.position.y)/ 2;
// print($ "i = {i}、rect = {rect.position}、vert1 = {vert1.position}、vert3 = {vert3.position}");
if(dicRect .Count> 0 &&(rect.y + 1 <dicRect [line] [dicRect [line] .Count-1] .y))
{ line ++; } if(dicRect.ContainsKey(line))
{{
dicRect [line] .Add(rect);
}
else
{ dicRect.Add(line、new List <Rect>(){rect}); } // print($ "line = {line}、dicrectcount = {dicRect.Count}"); } // print(JsonConvert.SerializeObject(dicRect)); foreach(dicRectのvar item) { // print($ "item key = {item.Key}、[f] = {item.Value [0] .position}、[l] = {item.Value [item.Value .Count-1] .position} "); Rect rect = new Rect(); var f = item.Value [0];
var l = item.Value [item.Value.Count-1];
rect.width = Math.Abs(fx --lx)+ f.width / 2 + l.width / 2;
rect.height = f.height;
rect.x = fx +(lx-fx)/ 2;
rect.y = fy;
// print($ "last item key = {item.Key}、{rect.position}");
hrefInfo.boxes.Add(rect);
}
}
}
/// <summary>
///ハイパーリンクが解析された後の最終出力テキストを取得します
/// </ summary>
/// <returns> </ returns>
protected virtual string GetOutputText(string outputText)
{ s_TextBuilder.Length = 0; m_HrefInfos.Clear(); var indexText = 0; foreach(s_HrefRegex.Matches(outputText)の一致一致) {
s_TextBuilder.Append(outputText.Substring(indexText、match.Index-indexText));
var group = match.Groups [1];
var str = Regex.Replace(s_TextBuilder.ToString()、@ "\ s"、 "") ;
// print($ "str = {str}");
var hrefInfo = new HyperlinkInfo
{ //スペースを削除し、リッチテキスト識別子を正しい位置にラップします startIndex = Regex.Replace(str、@ "<(。*? )> "、" ")。Length* 4、//ハイパーリンク内のテキストの開始頂点インデックス endIndex =(Regex.Replace(str、@" <(。*?)> "、" ").Length + Regex .Replace(Regex.Replace(match.Groups [2] .ToString()、@ "\ s"、 "") 、@ "<(。*?)>"、 "").Length-1)* 4 + 3、
name = group.Value
};
m_HrefInfos.Add(hrefInfo);
// print( "")
s_TextBuilder.Append(match.Groups [2] .Value);
indexText = match.Index + match.Length;
}
s_TextBuilder.Append(outputText.Substring(indexText、outputText.Length-indexText));
s_TextBuilder.ToString();を返します。
}
RectTransform createImage(Transform parent)
{ GameObject image = new GameObject(); var rect = image.AddComponent <RectTransform>(); var img = image.AddComponent <Image>(); img.raycastTarget = false; img.color = new Color(1、1、1、0.4f); image.transform.SetParent(parent); image.transform.localPosition = Vector3.zero; image.transform.localScale = Vector3.one; rectを返す; }
void trigger(Action <string> cb、Vector2 lp)
{ //画像サイズ2 * 2を作成して、クリックポイントを表示できますLp TO var point = createImage(transform); point.name = "clickpoint"; point.anchoredPosition = lp; point.sizeDelta = Vector2.one * 2; point.GetComponent <Image>()。color = Color.red;
foreach(HyperlinkInfo hrefInfo in m_HrefInfos)
{ var box = hrefInfo.boxes; // print($ "{Newtonsoft.Json.JsonConvert.SerializeObject(hrefInfo)}"); for(var i = 0; i <boxes.Count; + + i) { print($ "boxes [{i}] = {boxes [i]}"); //ボックス[i]の画像サイズを作成してクリック領域を表示できますTO //コメントでき ます// var box = createImage(transform); // box.name = "box" + hrefInfo.name; // box.sizeDelta = new Vector2(boxes [i] .width、boxes [i] .height); // box.anchoredPosition =新しいVector2(boxes [i] .x、boxes [i] .y);
if((boxes [i] .x --boxes [i] .width / 2)<lp.x &&(boxes [i] .x + boxs [i] .width / 2)> lp.x &&
(boxes [i ] .y --boxes [i] .height / 2)<lp.y &&(boxes [i] .y + boxs [i] .height / 2)> lp.y)
{ print( "点击了" + hrefInfo。名前); cb(hrefInfo.name); 戻る; } } } }
public void OnPointerClick(PointerEventData eventData)
{ Vector2 lp = Vector2.zero; print( "eventData Camera" + eventData.pressEventCamera.name); RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform、eventData.position、GameObject.FindGameObjectWithTag ( "UICamera")?GameObject.FindGameObjectWithTag( "UICamera")。GetComponent <Camera>() :eventData.pressEventCamera、out lp); for(int i = transform.childCount --1; i> = 0; i-) { // DestroyImmediate(transform.GetChild(i).gameObject); } trigger((s)=> {m_OnHrefClick。呼び出す; }、lp);
}
public void OnPointerDown(PointerEventData eventData)
{ recordTime = Time.time; isPointerDown = true; curlp = Vector2.zero; RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform、eventData.position、eventData.pressEventCamera、out curlp);
}
public void OnPointerUp(PointerEventData eventData)
{
isPointerDown = false;
PointUpAction.Invoke();
for(int i = transform.childCount --1; i> = 0; i-)
{ // DestroyImmediate (transform.GetChild(i).gameObject); } } void Update() { if(isPointerDown) { if(Time.timeScale!= 1) { 間隔= 0.6f; } else { 間隔= 0.3f; } if((Time.time-recordTime)> interval)
{ isPointerDown = false; // trigger((s)=> {m_OnHrefPress.Invoke(s);}、curlp); } } }
/// <summary>
///ハイパーリンクコールバックの現在のクリック
/// </ summary>
/// <
paramname = "info">コールバック情報</ param> private void OnHyperlinkTextInfo(string info)
{ // print( "クリック" +情報); }
}
}