首次提交

This commit is contained in:
Bob.Song
2026-03-05 18:07:55 +08:00
commit e125bb869e
4534 changed files with 563920 additions and 0 deletions

View File

@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace FairyGUI
{
/// <summary>
/// Base class for all kind of fonts.
/// </summary>
public class BaseFont
{
/// <summary>
/// The name of this font object.
/// </summary>
public string name;
/// <summary>
/// The texture of this font object.
/// </summary>
public NTexture mainTexture;
/// <summary>
/// Can this font be tinted? Will be true for dynamic font and fonts generated by BMFont.
/// </summary>
public bool canTint;
/// <summary>
/// If true, it will use extra vertices to enhance bold effect
/// </summary>
public bool customBold;
/// <summary>
/// If true, it will use extra vertices to enhance bold effect ONLY when it is in italic style.
/// </summary>
public bool customBoldAndItalic;
/// <summary>
/// If true, it will use extra vertices(4 direction) to enhance outline effect
/// </summary>
public bool customOutline;
/// <summary>
/// The shader for this font object.
/// </summary>
public string shader;
/// <summary>
/// Keep text crisp.
/// </summary>
public bool keepCrisp;
/// <summary>
///
/// </summary>
public int version;
protected internal static bool textRebuildFlag;
protected const float SupScale = 0.58f;
protected const float SupOffset = 0.33f;
virtual public void SetFormat(TextFormat format, float fontSizeScale)
{
}
virtual public void PrepareCharacters(string text, TextFormat format, float fontSizeScale)
{
}
virtual public void Prepare(TextFormat format)
{
}
virtual public bool BuildGraphics(NGraphics graphics)
{
return false;
}
virtual public void StartDraw(NGraphics graphics)
{
}
virtual public bool GetGlyph(char ch, out float width, out float height, out float baseline)
{
width = 0;
height = 0;
baseline = 0;
return false;
}
virtual public void DrawGlyph(VertexBuffer vb, float x, float y2)
{
}
virtual public void DrawLine(VertexBuffer vb, float x, float y, float width, int fontSize, int type)
{
}
virtual public bool HasCharacter(char ch)
{
return false;
}
virtual public int GetLineHeight(int size)
{
return 0;
}
virtual public void Dispose()
{
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 242acb07eafac7a43a60dc4107fbd6b4
timeCreated: 1460480287
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,174 @@
using System.Collections.Generic;
using UnityEngine;
namespace FairyGUI
{
/// <summary>
///
/// </summary>
public class BitmapFont : BaseFont
{
/// <summary>
///
/// </summary>
public class BMGlyph
{
public float x;
public float y;
public float width;
public float height;
public int advance;
public int lineHeight;
public Vector2[] uv = new Vector2[4];
public int channel;//0-n/a, 1-r,2-g,3-b,4-alpha
}
/// <summary>
///
/// </summary>
public int size;
/// <summary>
///
/// </summary>
public bool resizable;
/// <summary>
/// Font generated by BMFont use channels.
/// </summary>
public bool hasChannel;
protected Dictionary<int, BMGlyph> _dict;
protected BMGlyph _glyph;
float _scale;
public BitmapFont()
{
this.canTint = true;
this.hasChannel = false;
this.customOutline = true;
this.shader = ShaderConfig.bmFontShader;
_dict = new Dictionary<int, BMGlyph>();
_scale = 1;
}
public void AddChar(char ch, BMGlyph glyph)
{
_dict[ch] = glyph;
}
override public void SetFormat(TextFormat format, float fontSizeScale)
{
if (resizable)
_scale = (float)format.size / size * fontSizeScale;
else
_scale = fontSizeScale;
if (canTint)
format.FillVertexColors(vertexColors);
}
override public bool GetGlyph(char ch, out float width, out float height, out float baseline)
{
if (ch == ' ')
{
width = Mathf.RoundToInt(size * _scale / 2);
height = Mathf.RoundToInt(size * _scale);
baseline = height;
_glyph = null;
return true;
}
else if (_dict.TryGetValue((int)ch, out _glyph))
{
width = Mathf.RoundToInt(_glyph.advance * _scale);
height = Mathf.RoundToInt(_glyph.lineHeight * _scale);
baseline = height;
return true;
}
else
{
width = 0;
height = 0;
baseline = 0;
return false;
}
}
static Vector3 bottomLeft;
static Vector3 topLeft;
static Vector3 topRight;
static Vector3 bottomRight;
static Color32[] vertexColors = new Color32[4];
override public void DrawGlyph(VertexBuffer vb, float x, float y)
{
if (_glyph == null) //space
return;
topLeft.x = x + _glyph.x * _scale;
topLeft.y = y + (_glyph.lineHeight - _glyph.y) * _scale;
bottomRight.x = x + (_glyph.x + _glyph.width) * _scale;
bottomRight.y = topLeft.y - _glyph.height * _scale;
topRight.x = bottomRight.x;
topRight.y = topLeft.y;
bottomLeft.x = topLeft.x;
bottomLeft.y = bottomRight.y;
vb.vertices.Add(bottomLeft);
vb.vertices.Add(topLeft);
vb.vertices.Add(topRight);
vb.vertices.Add(bottomRight);
vb.uvs.AddRange(_glyph.uv);
if (hasChannel)
{
Vector2 channel = new Vector2(_glyph.channel, 0);
vb.uvs2.Add(channel);
vb.uvs2.Add(channel);
vb.uvs2.Add(channel);
vb.uvs2.Add(channel);
}
if (canTint)
{
vb.colors.Add(vertexColors[0]);
vb.colors.Add(vertexColors[1]);
vb.colors.Add(vertexColors[2]);
vb.colors.Add(vertexColors[3]);
}
else
{
vb.colors.Add(Color.white);
vb.colors.Add(Color.white);
vb.colors.Add(Color.white);
vb.colors.Add(Color.white);
}
}
override public bool HasCharacter(char ch)
{
return ch == ' ' || _dict.ContainsKey((int)ch);
}
override public int GetLineHeight(int size)
{
if (_dict.Count > 0)
{
using (var et = _dict.GetEnumerator())
{
et.MoveNext();
if (resizable)
return Mathf.RoundToInt((float)et.Current.Value.lineHeight * size / this.size);
else
return et.Current.Value.lineHeight;
}
}
else
return 0;
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: b1441c09e3389a046827b23ee409a37a
timeCreated: 1460480288
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,377 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace FairyGUI
{
/// <summary>
///
/// </summary>
public class DynamicFont : BaseFont
{
Font _font;
int _size;
float _ascent;
float _lineHeight;
float _scale;
TextFormat _format;
FontStyle _style;
bool _boldVertice;
CharacterInfo _char;
CharacterInfo _lineChar;
bool _gotLineChar;
public DynamicFont()
{
this.canTint = true;
this.keepCrisp = true;
this.customOutline = true;
this.shader = ShaderConfig.textShader;
}
/// <summary>
///
/// </summary>
/// <param name="name"></param>
/// <param name="font"></param>
/// <returns></returns>
public DynamicFont(string name, Font font) : this()
{
this.name = name;
this.nativeFont = font;
}
override public void Dispose()
{
Font.textureRebuilt -= textureRebuildCallback;
}
public Font nativeFont
{
get { return _font; }
set
{
if (_font != null)
Font.textureRebuilt -= textureRebuildCallback;
_font = value;
Font.textureRebuilt += textureRebuildCallback;
_font.hideFlags = DisplayObject.hideFlags;
_font.material.hideFlags = DisplayObject.hideFlags;
_font.material.mainTexture.hideFlags = DisplayObject.hideFlags;
if (mainTexture != null)
mainTexture.Dispose();
mainTexture = new NTexture(_font.material.mainTexture);
mainTexture.destroyMethod = DestroyMethod.None;
// _ascent = _font.ascent;
// _lineHeight = _font.lineHeight;
_ascent = _font.fontSize;
_lineHeight = _font.fontSize * 1.25f;
}
}
override public void SetFormat(TextFormat format, float fontSizeScale)
{
_format = format;
float size = format.size * fontSizeScale;
if (keepCrisp)
size *= UIContentScaler.scaleFactor;
if (_format.specialStyle == TextFormat.SpecialStyle.Subscript || _format.specialStyle == TextFormat.SpecialStyle.Superscript)
size *= SupScale;
_size = Mathf.FloorToInt(size);
if (_size == 0)
_size = 1;
_scale = (float)_size / _font.fontSize;
if (format.bold && !customBold)
{
if (format.italic)
{
if (customBoldAndItalic)
_style = FontStyle.Italic;
else
_style = FontStyle.BoldAndItalic;
}
else
_style = FontStyle.Bold;
}
else
{
if (format.italic)
_style = FontStyle.Italic;
else
_style = FontStyle.Normal;
}
_boldVertice = format.bold && (customBold || (format.italic && customBoldAndItalic));
format.FillVertexColors(vertexColors);
}
override public void PrepareCharacters(string text, TextFormat format, float fontSizeScale)
{
SetFormat(format, fontSizeScale);
_font.RequestCharactersInTexture(text, _size, _style);
}
override public bool GetGlyph(char ch, out float width, out float height, out float baseline)
{
if (!_font.GetCharacterInfo(ch, out _char, _size, _style))
{
if (ch == ' ')
{
//space may not be prepared, try again
_font.RequestCharactersInTexture(" ", _size, _style);
_font.GetCharacterInfo(ch, out _char, _size, _style);
}
else
{
width = height = baseline = 0;
return false;
}
}
width = _char.advance;
height = _lineHeight * _scale;
baseline = _ascent * _scale;
if (_boldVertice)
width++;
if (_format.specialStyle == TextFormat.SpecialStyle.Subscript)
{
height /= SupScale;
baseline /= SupScale;
}
else if (_format.specialStyle == TextFormat.SpecialStyle.Superscript)
{
height = height / SupScale + baseline * SupOffset;
baseline *= (SupOffset + 1 / SupScale);
}
height = Mathf.RoundToInt(height);
baseline = Mathf.RoundToInt(baseline);
if (keepCrisp)
{
width /= UIContentScaler.scaleFactor;
height /= UIContentScaler.scaleFactor;
baseline /= UIContentScaler.scaleFactor;
}
return true;
}
static Vector3 bottomLeft;
static Vector3 topLeft;
static Vector3 topRight;
static Vector3 bottomRight;
static Vector2 uvBottomLeft;
static Vector2 uvTopLeft;
static Vector2 uvTopRight;
static Vector2 uvBottomRight;
static Color32[] vertexColors = new Color32[4];
static Vector3[] BOLD_OFFSET = new Vector3[]
{
new Vector3(-0.5f, 0f, 0f),
new Vector3(0.5f, 0f, 0f),
new Vector3(0f, -0.5f, 0f),
new Vector3(0f, 0.5f, 0f)
};
override public void DrawGlyph(VertexBuffer vb, float x, float y)
{
topLeft.x = _char.minX;
topLeft.y = _char.maxY;
bottomRight.x = _char.maxX;
if (_char.glyphWidth == 0) //zero width, space etc
bottomRight.x = topLeft.x + _size / 2;
bottomRight.y = _char.minY;
if (keepCrisp)
{
topLeft /= UIContentScaler.scaleFactor;
bottomRight /= UIContentScaler.scaleFactor;
}
if (_format.specialStyle == TextFormat.SpecialStyle.Subscript)
y = y - Mathf.RoundToInt(_ascent * _scale * SupOffset);
else if (_format.specialStyle == TextFormat.SpecialStyle.Superscript)
y = y + Mathf.RoundToInt(_ascent * _scale * (1 / SupScale - 1 + SupOffset));
topLeft.x += x;
topLeft.y += y;
bottomRight.x += x;
bottomRight.y += y;
topRight.x = bottomRight.x;
topRight.y = topLeft.y;
bottomLeft.x = topLeft.x;
bottomLeft.y = bottomRight.y;
vb.vertices.Add(bottomLeft);
vb.vertices.Add(topLeft);
vb.vertices.Add(topRight);
vb.vertices.Add(bottomRight);
uvBottomLeft = _char.uvBottomLeft;
uvTopLeft = _char.uvTopLeft;
uvTopRight = _char.uvTopRight;
uvBottomRight = _char.uvBottomRight;
vb.uvs.Add(uvBottomLeft);
vb.uvs.Add(uvTopLeft);
vb.uvs.Add(uvTopRight);
vb.uvs.Add(uvBottomRight);
vb.colors.Add(vertexColors[0]);
vb.colors.Add(vertexColors[1]);
vb.colors.Add(vertexColors[2]);
vb.colors.Add(vertexColors[3]);
if (_boldVertice)
{
for (int b = 0; b < 4; b++)
{
Vector3 boldOffset = BOLD_OFFSET[b];
vb.vertices.Add(bottomLeft + boldOffset);
vb.vertices.Add(topLeft + boldOffset);
vb.vertices.Add(topRight + boldOffset);
vb.vertices.Add(bottomRight + boldOffset);
vb.uvs.Add(uvBottomLeft);
vb.uvs.Add(uvTopLeft);
vb.uvs.Add(uvTopRight);
vb.uvs.Add(uvBottomRight);
vb.colors.Add(vertexColors[0]);
vb.colors.Add(vertexColors[1]);
vb.colors.Add(vertexColors[2]);
vb.colors.Add(vertexColors[3]);
}
}
}
override public void DrawLine(VertexBuffer vb, float x, float y, float width, int fontSize, int type)
{
if (!_gotLineChar)
{
_gotLineChar = true;
_font.RequestCharactersInTexture("_", 50, FontStyle.Normal);
_font.GetCharacterInfo('_', out _lineChar, 50, FontStyle.Normal);
}
float thickness;
float offset;
thickness = Mathf.Max(1, fontSize / 16f); //guest underline size
if (type == 0)
offset = Mathf.RoundToInt(_lineChar.minY * (float)fontSize / 50 + thickness);
else
offset = Mathf.RoundToInt(_ascent * 0.4f * fontSize / _font.fontSize);
if (thickness < 1)
thickness = 1;
topLeft.x = x;
topLeft.y = y + offset;
bottomRight.x = x + width;
bottomRight.y = topLeft.y - thickness;
topRight.x = bottomRight.x;
topRight.y = topLeft.y;
bottomLeft.x = topLeft.x;
bottomLeft.y = bottomRight.y;
vb.vertices.Add(bottomLeft);
vb.vertices.Add(topLeft);
vb.vertices.Add(topRight);
vb.vertices.Add(bottomRight);
uvBottomLeft = _lineChar.uvBottomLeft;
uvTopLeft = _lineChar.uvTopLeft;
uvTopRight = _lineChar.uvTopRight;
uvBottomRight = _lineChar.uvBottomRight;
//取中点的UV
Vector2 u0;
if (_lineChar.uvBottomLeft.x != _lineChar.uvBottomRight.x)
u0.x = (_lineChar.uvBottomLeft.x + _lineChar.uvBottomRight.x) * 0.5f;
else
u0.x = (_lineChar.uvBottomLeft.x + _lineChar.uvTopLeft.x) * 0.5f;
if (_lineChar.uvBottomLeft.y != _lineChar.uvTopLeft.y)
u0.y = (_lineChar.uvBottomLeft.y + _lineChar.uvTopLeft.y) * 0.5f;
else
u0.y = (_lineChar.uvBottomLeft.y + _lineChar.uvBottomRight.y) * 0.5f;
vb.uvs.Add(u0);
vb.uvs.Add(u0);
vb.uvs.Add(u0);
vb.uvs.Add(u0);
vb.colors.Add(vertexColors[0]);
vb.colors.Add(vertexColors[1]);
vb.colors.Add(vertexColors[2]);
vb.colors.Add(vertexColors[3]);
if (_boldVertice)
{
for (int b = 0; b < 4; b++)
{
Vector3 boldOffset = BOLD_OFFSET[b];
vb.vertices.Add(bottomLeft + boldOffset);
vb.vertices.Add(topLeft + boldOffset);
vb.vertices.Add(topRight + boldOffset);
vb.vertices.Add(bottomRight + boldOffset);
vb.uvs.Add(u0);
vb.uvs.Add(u0);
vb.uvs.Add(u0);
vb.uvs.Add(u0);
vb.colors.Add(vertexColors[0]);
vb.colors.Add(vertexColors[1]);
vb.colors.Add(vertexColors[2]);
vb.colors.Add(vertexColors[3]);
}
}
}
override public bool HasCharacter(char ch)
{
return _font.HasCharacter(ch);
}
override public int GetLineHeight(int size)
{
return Mathf.RoundToInt(_lineHeight * size / _font.fontSize);
}
void textureRebuildCallback(Font targetFont)
{
if (_font != targetFont)
return;
if (mainTexture == null || !Application.isPlaying)
{
mainTexture = new NTexture(_font.material.mainTexture);
mainTexture.destroyMethod = DestroyMethod.None;
}
else
mainTexture.Reload(_font.material.mainTexture, null);
_gotLineChar = false;
textRebuildFlag = true;
version++;
//Debug.Log("Font texture rebuild: " + name + "," + mainTexture.width + "," + mainTexture.height);
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 37b73f8527098974cb0ccf518ff95351
timeCreated: 1535374214
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
namespace FairyGUI
{
/// <summary>
///
/// </summary>
public class Emoji
{
/// <summary>
/// 代表图片资源url。
/// </summary>
public string url;
/// <summary>
/// 图片宽度。不设置0则表示使用原始宽度。
/// </summary>
public int width;
/// <summary>
/// 图片高度。不设置0则表示使用原始高度。
/// </summary>
public int height;
/// <summary>
///
/// </summary>
/// <param name="url"></param>
/// <param name="width"></param>
/// <param name="height"></param>
public Emoji(string url, int width, int height)
{
this.url = url;
this.width = width;
this.height = height;
}
/// <summary>
///
/// </summary>
/// <param name="url"></param>
public Emoji(string url)
{
this.url = url;
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 3859ae9020061394cadacd1624e04ed9
timeCreated: 1475139464
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace FairyGUI
{
/// <summary>
///
/// </summary>
public class FontManager
{
public static Dictionary<string, BaseFont> sFontFactory = new Dictionary<string, BaseFont>();
static bool _checkTextMeshPro;
/// <summary>
///
/// </summary>
/// <param name="font"></param>
/// <param name="alias"></param>
static public void RegisterFont(BaseFont font, string alias = null)
{
sFontFactory[font.name] = font;
if (alias != null)
sFontFactory[alias] = font;
}
/// <summary>
///
/// </summary>
/// <param name="font"></param>
static public void UnregisterFont(BaseFont font)
{
List<string> toDelete = new List<string>();
foreach (KeyValuePair<string, BaseFont> kv in sFontFactory)
{
if (kv.Value == font)
toDelete.Add(kv.Key);
}
foreach (string key in toDelete)
sFontFactory.Remove(key);
}
/// <summary>
///
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
static public BaseFont GetFont(string name)
{
BaseFont font;
if (name.StartsWith(UIPackage.URL_PREFIX))
{
font = UIPackage.GetItemAssetByURL(name) as BaseFont;
if (font != null)
return font;
}
if (sFontFactory.TryGetValue(name, out font))
return font;
object asset = Resources.Load(name);
if (asset == null)
asset = Resources.Load("Fonts/" + name);
//Try to use new API in Uinty5 to load
if (asset == null)
{
if (name.IndexOf(",") != -1)
{
string[] arr = name.Split(',');
int cnt = arr.Length;
for (int i = 0; i < cnt; i++)
arr[i] = arr[i].Trim();
asset = Font.CreateDynamicFontFromOSFont(arr, 16);
}
else
asset = Font.CreateDynamicFontFromOSFont(name, 16);
}
if (asset == null)
return Fallback(name);
if (asset is Font)
{
font = new DynamicFont();
font.name = name;
sFontFactory.Add(name, font);
((DynamicFont)font).nativeFont = (Font)asset;
}
#if FAIRYGUI_TMPRO
else if (asset is TMPro.TMP_FontAsset)
{
font = new TMPFont();
font.name = name;
sFontFactory.Add(name, font);
((TMPFont)font).fontAsset = (TMPro.TMP_FontAsset)asset;
}
#endif
else
{
if (asset.GetType().Name.Contains("TMP_FontAsset"))
{
if (!_checkTextMeshPro)
{
_checkTextMeshPro = true;
Debug.LogWarning("To enable TextMeshPro support, add script define symbol: FAIRYGUI_TMPRO");
}
}
return Fallback(name);
}
return font;
}
static BaseFont Fallback(string name)
{
if (name != UIConfig.defaultFont)
{
BaseFont ff;
if (sFontFactory.TryGetValue(UIConfig.defaultFont, out ff))
{
sFontFactory[name] = ff;
return ff;
}
}
Font asset = (Font)Resources.GetBuiltinResource(typeof(Font), "Arial.ttf");
if (asset == null)
throw new Exception("Failed to load font '" + name + "'");
BaseFont font = new DynamicFont();
font.name = name;
((DynamicFont)font).nativeFont = asset;
sFontFactory.Add(name, font);
return font;
}
/// <summary>
///
/// </summary>
static public void Clear()
{
foreach (KeyValuePair<string, BaseFont> kv in sFontFactory)
kv.Value.Dispose();
sFontFactory.Clear();
}
#if UNITY_2019_3_OR_NEWER
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void InitializeOnLoad()
{
Clear();
_checkTextMeshPro = false;
}
#endif
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 5084c28e388b94a4fa4e2a80485296b3
timeCreated: 1535374214
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,42 @@
namespace FairyGUI
{
/// <summary>
/// 用于文本输入的键盘接口
/// </summary>
public interface IKeyboard
{
/// <summary>
/// 键盘已收回,输入已完成
/// </summary>
bool done { get; }
/// <summary>
/// 是否支持在光标处输入。如果为trueGetInput返回的是在当前光标处需要插入的文本如果为falseGetInput返回的是整个文本。
/// </summary>
bool supportsCaret { get; }
/// <summary>
/// 用户输入的文本。
/// </summary>
/// <returns></returns>
string GetInput();
/// <summary>
/// 打开键盘
/// </summary>
/// <param name="text"></param>
/// <param name="autocorrection"></param>
/// <param name="multiline"></param>
/// <param name="secure"></param>
/// <param name="alert"></param>
/// <param name="textPlaceholder"></param>
/// <param name="keyboardType"></param>
/// <param name="hideInput"></param>
void Open(string text, bool autocorrection, bool multiline, bool secure, bool alert, string textPlaceholder, int keyboardType, bool hideInput);
/// <summary>
/// 关闭键盘
/// </summary>
void Close();
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 4e3b9d951c903b049b8495c2d16f67fe
timeCreated: 1460480287
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 87f693de944eb7d4ab4ccb9b65af352a
timeCreated: 1535374214
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,701 @@
/********************************************************************
Copyright (c) 2018, Tadpole Studio
All rights reserved
文件名称: RTL.cs
说 明: RTL字符转换
版 本: 1.00
时 间: 2018/2/24 9:02:12
作 者: AQ QQ:355010366
概 述: 新建
*********************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
namespace FairyGUI
{
public class RTLSupport
{
internal enum CharState
{
isolated,
final,
lead,
middle,
}
// Bidirectional Character Types
public enum DirectionType
{
UNKNOW = 0,
LTR,
RTL,
NEUTRAL,
}
#if RTL_TEXT_SUPPORT
public static DirectionType BaseDirection = DirectionType.RTL; // 主体语言是否是RTL的语言
#else
public static DirectionType BaseDirection = DirectionType.UNKNOW;
#endif
private static bool isCharsInitialized = false;
private static Dictionary<int, char[]> mapping = new Dictionary<int, char[]>();
private static List<char> listFinal = new List<char>();
private static List<string> listRep = new List<string>();
private static StringBuilder sbRep = new StringBuilder();
private static StringBuilder sbN = new StringBuilder();
private static StringBuilder sbFinal = new StringBuilder();
private static StringBuilder sbReverse = new StringBuilder();
public static bool IsArabicLetter(char ch)
{
if (ch >= 0x600 && ch <= 0x6ff)
{
if ((ch >= 0x660 && ch <= 0x66D) || (ch >= 0x6f0 && ch <= 0x6f9)) // 标准阿拉伯语数字和东阿拉伯语数字 [2019/3/1/ 17:45:18 by aq_1000]
{
return false;
}
return true;
}
else if (ch >= 0x750 && ch <= 0x77f)
return true;
else if (ch >= 0xfb50 && ch <= 0xfc3f)
return true;
else if (ch >= 0xfe70 && ch <= 0xfefc)
return true;
return false;
}
public static string ConvertNumber(string strNumber)
{
sbRep.Length = 0;
foreach (char ch in strNumber)
{
int un = ch;
if (un == 0x66c || ch == ',') // 去掉逗号
continue;
else if (un == 0x660 || un == 0x6f0)
sbRep.Append('0');
else if (un == 0x661 || un == 0x6f1)
sbRep.Append('1');
else if (un == 0x662 || un == 0x6f2)
sbRep.Append('2');
else if (un == 0x663 || un == 0x6f3)
sbRep.Append('3');
else if (un == 0x664 || un == 0x6f4)
sbRep.Append('4');
else if (un == 0x665 || un == 0x6f5)
sbRep.Append('5');
else if (un == 0x666 || un == 0x6f6)
sbRep.Append('6');
else if (un == 0x667 || un == 0x6f7)
sbRep.Append('7');
else if (un == 0x668 || un == 0x6f8)
sbRep.Append('8');
else if (un == 0x669 || un == 0x6f9)
sbRep.Append('9');
else
sbRep.Append(ch);
}
return sbRep.ToString();
}
public static bool ContainsArabicLetters(string text)
{
foreach (char character in text)
{
if (character >= 0x600 && character <= 0x6ff)
return true;
if (character >= 0x750 && character <= 0x77f)
return true;
if (character >= 0xfb50 && character <= 0xfc3f)
return true;
if (character >= 0xfe70 && character <= 0xfefc)
return true;
}
return false;
}
// 检测文本主方向
public static DirectionType DetectTextDirection(string text)
{
bool isContainRTL = false;
bool isContainLTR = false;
foreach (char ch in text)
{
if (IsArabicLetter(ch))
{
isContainRTL = true;
if (isContainLTR)
break;
}
else if (char.IsLetter(ch))
{
isContainLTR = true;
if (isContainRTL)
break;
}
}
if (!isContainRTL)
return DirectionType.UNKNOW; // 这边unknow暂时代表文本一个RTL字符都没有无需进行RTL转换
else if (!isContainLTR)
return DirectionType.RTL;
return BaseDirection;
}
private static bool CheckSeparator(char input)
{
if (!IsArabicLetter(input))
{
return true;
}
else
{
return (input == '،') || (input == '?') || (input == '؟');
}
// if ((input != ' ') && (input != '\t') && (input != '!') && (input != '.') &&
// (input != '،') && (input != '?') && (input != '؟') &&
// !_IsBracket(input) && // 括号也算 [2018/8/1/ 15:12:20 by aq_1000]
// !_IsNeutrality(input))
// {
// return false;
// }
// return true;
}
private static bool CheckSpecific(char input)
{
int num = input;
if ((num != 0x622) && (num != 0x623) && (num != 0x627) && (num != 0x62f) && (num != 0x625) &&
(num != 0x630) && (num != 0x631) && (num != 0x632) && (num != 0x698) && (num != 0x648) &&
!_CheckSoundmark(input))
{
return false;
}
return true;
}
private static bool _CheckSoundmark(char ch)
{
int un = ch;
return (un >= 0x610 && un <= 0x61e) || (un >= 0x64b && un <= 0x65f);
}
public static string DoMapping(string input)
{
if (!isCharsInitialized)
{
isCharsInitialized = true;
InitChars();
}
// 伊斯兰教真主安拉在阿拉伯文里写作الله
// 键盘输入时输入 ل (lam) + ل (lam) + ه (ha) 后会自动转换成带记号的符号。 [2018/3/13 20:03:45 --By aq_1000]
if (input == "الله")
{
input = "ﷲ";
}
sbFinal.Length = 0;
sbFinal.Append(input);
char perChar = '\0';
for (int i = 0; i < sbFinal.Length; i++)
{
if (!mapping.ContainsKey(sbFinal[i]))
{
perChar = sbFinal[i];
continue;
}
if ((i + 1) == sbFinal.Length)
{
if (sbFinal.Length == 1)
{
perChar = sbFinal[i];
sbFinal[i] = mapping[sbFinal[i]][(int)CharState.isolated];
}
else if (CheckSeparator(perChar) || CheckSpecific(perChar))
{
perChar = sbFinal[i];
sbFinal[i] = mapping[sbFinal[i]][(int)CharState.isolated];
}
else
{
perChar = sbFinal[i];
sbFinal[i] = mapping[sbFinal[i]][(int)CharState.final];
}
}
else if (i == 0)
{
if (!CheckSeparator(sbFinal[i + 1]))
{
perChar = sbFinal[i];
sbFinal[i] = mapping[sbFinal[i]][(int)CharState.lead];
}
else
{
perChar = sbFinal[i];
sbFinal[i] = mapping[sbFinal[i]][(int)CharState.isolated];
}
}
else if (CheckSeparator(sbFinal[i + 1]))
{
if (CheckSeparator(perChar) || CheckSpecific(perChar))
{
perChar = sbFinal[i];
sbFinal[i] = mapping[sbFinal[i]][(int)CharState.isolated];
}
else
{
perChar = sbFinal[i];
sbFinal[i] = mapping[sbFinal[i]][(int)CharState.final];
}
}
else if (CheckSeparator(perChar))
{
if (CheckSeparator(sbFinal[i + 1]))
{
perChar = sbFinal[i];
sbFinal[i] = mapping[sbFinal[i]][(int)CharState.isolated];
}
else
{
perChar = sbFinal[i];
sbFinal[i] = mapping[sbFinal[i]][(int)CharState.lead];
}
}
else if (CheckSpecific(sbFinal[i + 1]))
{
if (CheckSeparator(perChar) || CheckSpecific(perChar))
{
perChar = sbFinal[i];
sbFinal[i] = mapping[sbFinal[i]][(int)CharState.lead];
}
else
{
perChar = sbFinal[i];
sbFinal[i] = mapping[sbFinal[i]][(int)CharState.middle];
}
}
else if (CheckSpecific(perChar))
{
if (CheckSeparator(sbFinal[i + 1]))
{
perChar = sbFinal[i];
sbFinal[i] = mapping[sbFinal[i]][(int)CharState.isolated];
}
else
{
perChar = sbFinal[i];
sbFinal[i] = mapping[sbFinal[i]][(int)CharState.lead];
}
}
else
{
perChar = sbFinal[i];
sbFinal[i] = mapping[sbFinal[i]][(int)CharState.middle];
}
}
return sbFinal.ToString();
}
// 主体语言是LTR
public static string ConvertLineL(string source)
{
listFinal.Clear();
listRep.Clear();
sbRep.Length = 0;
sbN.Length = 0;
int iReplace = 0;
DirectionType ePre = DirectionType.LTR;
char nextChar = '\0';
for (int j = 0; j < source.Length; j++)
{
if (j < source.Length - 1)
nextChar = source[j + 1];
else
nextChar = '\0';
char item = source[j];
DirectionType eCType = _GetDirection(item, nextChar, ePre, DirectionType.LTR);
if (eCType == DirectionType.RTL)
{
if (sbRep.Length == 0)
{
listFinal.Add('\x00bf');
iReplace++;
}
if (sbN.Length > 0)
sbRep.Append(sbN.ToString());
sbN.Length = 0;
sbRep.Append(item);
}
else if (eCType == DirectionType.LTR)
{
if (sbRep.Length > 0)
{
listRep.Add(sbRep.ToString());
}
sbRep.Length = 0;
if (sbN.Length > 0)
{
for (int n = 0; n < sbN.Length; ++n)
{
listFinal.Add(sbN[n]);
}
}
sbN.Length = 0;
// item = _ProcessBracket(item); // 文本主方向为LTR的话括号不需要翻转 [2018/12/20/ 17:03:23 by aq_1000]
listFinal.Add(item);
}
else
{
sbN.Append(item);
}
ePre = eCType;
}
if (sbRep.Length > 0)
{
listRep.Add(sbRep.ToString());
}
// 一行中都只有中立字符的情况,就直接返回中立字符 [2018/12/6/ 16:34:38 by aq_1000]
if (sbN.Length > 0)
{
for (int n = 0; n < sbN.Length; ++n)
{
listFinal.Add(sbN[n]);
}
}
sbRep.Length = 0;
sbN.Length = 0;
sbFinal.Length = 0;
sbFinal.Append(listFinal.ToArray());
for (int m = 0; m < iReplace; m++)
{
for (int n = 0; n < sbFinal.Length; n++)
{
if (sbFinal[n] == '\x00bf')
{
sbRep.Length = 0;
sbRep.Append(_Reverse(listRep[0]));
listRep.RemoveAt(0);
// 字符串反向的时候造成末尾空格跑到词首 [2018/4/11 20:04:35 --By aq_1000]
sbN.Length = 0;
for (int num4 = 0; num4 < sbRep.Length; num4++)
{
if (!_IsNeutrality(sbRep[num4]))
break;
sbN.Append(sbRep[num4]);
}
if (sbN.Length > 0) // 词首空格重新放到词尾
{
sbRep.Remove(0, sbN.Length);
for (int iSpace = sbN.Length - 1; iSpace >= 0; --iSpace) // 空格也要取反
{
sbRep.Append(sbN[iSpace]);
}
}
sbFinal.Replace(sbFinal[n].ToString(), sbRep.ToString(), n, 1);
break;
}
}
}
return sbFinal.ToString();
}
// 主体语言是RTL整个文本就从右往左读LTR语言就作为嵌入语段处理
public static string ConvertLineR(string source)
{
listFinal.Clear();
listRep.Clear();
sbRep.Length = 0;
sbN.Length = 0;
int iReplace = 0;
DirectionType ePre = DirectionType.RTL;
char nextChar = '\0';
for (int j = 0; j < source.Length; j++)
{
if (j < source.Length - 1)
nextChar = source[j + 1];
else
nextChar = '\0';
char item = source[j];
DirectionType eCType = _GetDirection(item, nextChar, ePre, DirectionType.RTL);
if (eCType == DirectionType.LTR)
{
if (sbRep.Length == 0)
{
listFinal.Add('\x00bf');
iReplace++;
}
if (sbN.Length > 0)
sbRep.Append(sbN.ToString());
sbN.Length = 0;
sbRep.Append(item);
}
else if (eCType == DirectionType.RTL)
{
if (sbRep.Length > 0)
{
listRep.Add(sbRep.ToString());
}
sbRep.Length = 0;
if (sbN.Length > 0)
{
for (int n = 0; n < sbN.Length; ++n)
{
listFinal.Add(sbN[n]);
}
}
sbN.Length = 0;
item = _ProcessBracket(item);
listFinal.Add(item);
}
else
{
sbN.Append(item);
}
ePre = eCType;
}
if (sbRep.Length > 0)
{
listRep.Add(sbRep.ToString());
}
// 一行中都只有中立字符的情况,就直接返回中立字符 [2018/12/6/ 16:34:38 by aq_1000]
if (sbN.Length > 0)
{
for (int n = 0; n < sbN.Length; ++n)
{
listFinal.Add(sbN[n]);
}
}
sbFinal.Length = 0;
sbFinal.Append(listFinal.ToArray());
for (int m = 0; m < iReplace; m++)
{
for (int n = 0; n < sbFinal.Length; n++)
{
if (sbFinal[n] == '\x00bf')
{
sbRep.Length = 0;
sbRep.Append(_Reverse(listRep[0]));
listRep.RemoveAt(0);
// 字符串反向的时候造成末尾空格跑到词首 [2018/4/11 20:04:35 --By aq_1000]
sbN.Length = 0;
for (int num4 = 0; num4 < sbRep.Length; num4++)
{
if (!_IsNeutrality(sbRep[num4]))
break;
sbN.Append(sbRep[num4]);
}
if (sbN.Length > 0) // 词首空格重新放到词尾
{
sbRep.Remove(0, sbN.Length);
for (int iSpace = sbN.Length - 1; iSpace >= 0; --iSpace) // 空格也要取反
{
sbRep.Append(sbN[iSpace]);
}
}
sbFinal.Replace(sbFinal[n].ToString(), sbRep.ToString(), n, 1);
break;
}
}
}
return sbFinal.ToString();
}
private static string _Reverse(string source)
{
sbReverse.Length = 0;
int len = source.Length;
int i = len - 1;
while (i >= 0)
{
char ch = source[i];
if (ch == '\r' && i != len - 1 && source[i + 1] == '\n')
{
i--;
continue;
}
if (char.IsLowSurrogate(ch)) //不要反向高低代理对
{
sbReverse.Append(source[i - 1]);
sbReverse.Append(ch);
i--;
}
else
sbReverse.Append(ch);
i--;
}
return sbReverse.ToString();
}
private static void InitChars()
{
// {isolated,final,lead,middle} [2018/11/27 16:04:18 --By aq_1000]
mapping.Add(0x621, new char[4] { (char)0xFE80, (char)0xFE8A, (char)0xFE8B, (char)0xFE8C }); // Hamza
mapping.Add(0x627, new char[4] { (char)0xFE8D, (char)0xFE8E, (char)0xFE8D, (char)0xFE8E }); // Alef
mapping.Add(0x623, new char[4] { (char)0xFE83, (char)0xFE84, (char)0xFE83, (char)0xFE84 }); // AlefHamza
mapping.Add(0x624, new char[4] { (char)0xFE85, (char)0xFE85, (char)0xFE85, (char)0xFE85 }); // WawHamza
mapping.Add(0x625, new char[4] { (char)0xFE87, (char)0xFE87, (char)0xFE87, (char)0xFE87 }); // AlefMaksoor
mapping.Add(0x649, new char[4] { (char)0xFBFC, (char)0xFBFD, (char)0xFBFE, (char)0xFBFF }); // AlefMagsora
mapping.Add(0x626, new char[4] { (char)0xFE89, (char)0xFE8A, (char)0xFE8B, (char)0xFE8C }); // HamzaNabera
mapping.Add(0x628, new char[4] { (char)0xFE8F, (char)0xFE90, (char)0xFE91, (char)0xFE92 }); // Ba
mapping.Add(0x62A, new char[4] { (char)0xFE95, (char)0xFE96, (char)0xFE97, (char)0xFE98 }); // Ta
mapping.Add(0x62B, new char[4] { (char)0xFE99, (char)0xFE9A, (char)0xFE9B, (char)0xFE9C }); // Tha2
mapping.Add(0x62C, new char[4] { (char)0xFE9D, (char)0xFE9E, (char)0xFE9F, (char)0xFEA0 }); // Jeem
mapping.Add(0x62D, new char[4] { (char)0xFEA1, (char)0xFEA2, (char)0xFEA3, (char)0xFEA4 }); // H7aa
mapping.Add(0x62E, new char[4] { (char)0xFEA5, (char)0xFEA6, (char)0xFEA7, (char)0xFEA8 }); // Khaa2
mapping.Add(0x62F, new char[4] { (char)0xFEA9, (char)0xFEAA, (char)0xFEA9, (char)0xFEAA }); // Dal
mapping.Add(0x630, new char[4] { (char)0xFEAB, (char)0xFEAC, (char)0xFEAB, (char)0xFEAC }); // Thal
mapping.Add(0x631, new char[4] { (char)0xFEAD, (char)0xFEAE, (char)0xFEAD, (char)0xFEAD }); // Ra2
mapping.Add(0x632, new char[4] { (char)0xFEAF, (char)0xFEB0, (char)0xFEAF, (char)0xFEB0 }); // Zeen
mapping.Add(0x633, new char[4] { (char)0xFEB1, (char)0xFEB2, (char)0xFEB3, (char)0xFEB4 }); // Seen
mapping.Add(0x634, new char[4] { (char)0xFEB5, (char)0xFEB6, (char)0xFEB7, (char)0xFEB8 }); // Sheen
mapping.Add(0x635, new char[4] { (char)0xFEB9, (char)0xFEBA, (char)0xFEBB, (char)0xFEBC }); // S9a
mapping.Add(0x636, new char[4] { (char)0xFEBD, (char)0xFEBE, (char)0xFEBF, (char)0xFEC0 }); // Dha
mapping.Add(0x637, new char[4] { (char)0xFEC1, (char)0xFEC2, (char)0xFEC3, (char)0xFEC4 }); // T6a
mapping.Add(0x638, new char[4] { (char)0xFEC5, (char)0xFEC6, (char)0xFEC7, (char)0xFEC8 }); // T6ha
mapping.Add(0x639, new char[4] { (char)0xFEC9, (char)0xFECA, (char)0xFECB, (char)0xFECC }); // Ain
mapping.Add(0x63A, new char[4] { (char)0xFECD, (char)0xFECE, (char)0xFECF, (char)0xFED0 }); // Gain
mapping.Add(0x641, new char[4] { (char)0xFED1, (char)0xFED2, (char)0xFED3, (char)0xFED4 }); // Fa
mapping.Add(0x642, new char[4] { (char)0xFED5, (char)0xFED6, (char)0xFED7, (char)0xFED8 }); // Gaf
mapping.Add(0x643, new char[4] { (char)0xFED9, (char)0xFEDA, (char)0xFEDB, (char)0xFEDC }); // Kaf
mapping.Add(0x644, new char[4] { (char)0xFEDD, (char)0xFEDE, (char)0xFEDF, (char)0xFEE0 }); // Lam
mapping.Add(0x645, new char[4] { (char)0xFEE1, (char)0xFEE2, (char)0xFEE3, (char)0xFEE4 }); // Meem
mapping.Add(0x646, new char[4] { (char)0xFEE5, (char)0xFEE6, (char)0xFEE7, (char)0xFEE8 }); // Noon
mapping.Add(0x647, new char[4] { (char)0xFEE9, (char)0xFEEA, (char)0xFEEB, (char)0xFEEC }); // Ha
mapping.Add(0x648, new char[4] { (char)0xFEED, (char)0xFEEE, (char)0xFEED, (char)0xFEEE }); // Waw
mapping.Add(0x64A, new char[4] { (char)0xFEF1, (char)0xFEF2, (char)0xFEF3, (char)0xFEF4 }); // Ya
mapping.Add(0x622, new char[4] { (char)0xFE81, (char)0xFE81, (char)0xFE81, (char)0xFE81 }); // AlefMad
mapping.Add(0x629, new char[4] { (char)0xFE93, (char)0xFE94, (char)0xFE94, (char)0xFE94 }); // TaMarboota // 该字符只会出现在末尾 [2018/4/10 16:04:18 --By aq_1000]
mapping.Add(0x67E, new char[4] { (char)0xFB56, (char)0xFB57, (char)0xFB58, (char)0xFB59 }); // PersianPe
mapping.Add(0x686, new char[4] { (char)0xFB7A, (char)0xFB7B, (char)0xFB7C, (char)0xFB7D }); // PersianChe
mapping.Add(0x698, new char[4] { (char)0xFB8A, (char)0xFB8B, (char)0xFB8A, (char)0xFB8B }); // PersianZe
mapping.Add(0x6AF, new char[4] { (char)0xFB92, (char)0xFB93, (char)0xFB94, (char)0xFB95 }); // PersianGaf
mapping.Add(0x6A9, new char[4] { (char)0xFB8E, (char)0xFB8F, (char)0xFB90, (char)0xFB91 }); // PersianGaf2
mapping.Add(0x6BE, new char[4] { (char)0xFEE9, (char)0xFEEA, (char)0xFEEB, (char)0xFEEC });
mapping.Add(0x6CC, new char[4] { (char)0xFBFC, (char)0xFBFD, (char)0xFBFE, (char)0xFBFF });
}
// 是否中立方向字符
private static bool _IsNeutrality(char uc)
{
return (uc == ':' || uc == '' || uc == ' ' || /*uc == '%' ||*/ /*uc == '+' ||*/ /*uc == '-' ||*/ uc == '\n' || uc == '\r' || uc == '\t' || uc == '@' ||
(uc >= 0x2600 && uc <= 0x27BF)); // 表情符号
}
// 是否句末标点符号
private static bool _IsEndPunctuation(char uc, char nextChar)
{
if (uc == '.')
return _IsNeutrality(nextChar);
return (uc == '!' || uc == '' || uc == '。' || uc == '،' || uc == '?' || uc == '؟');
}
// 判断字符方向
private static DirectionType _GetDirection(char uc, char nextChar, DirectionType ePre, DirectionType eBase)
{
DirectionType eCType = ePre;
int uni = uc;
if (_IsBracket(uc) || _IsEndPunctuation(uc, nextChar))
{
eCType = eBase; // 括号和句末标点符号,方向根据上个字符为准 [2018/12/26/ 15:56:24 by aq_1000]
}
else if ((uni >= 0x660) && (uni <= 0x66D))
{
eCType = DirectionType.LTR;
}
else if (IsArabicLetter(uc) || uc == '+' /*|| uc == '-'*/ || uc == '%')
{
eCType = DirectionType.RTL;
}
else if (uc == '-')
{
if (char.IsNumber(nextChar))
eCType = DirectionType.LTR;
else
eCType = DirectionType.RTL;
}
else if (_IsNeutrality(uc)) // 中立方向字符,方向就和上一个字符一样 [2018/3/24 16:03:27 --By aq_1000]
{
if (ePre == DirectionType.UNKNOW || ePre == DirectionType.NEUTRAL)
{
if (char.IsNumber(nextChar)) // 数字都是弱LTR方向符开头中立字符后面紧跟着数字的话中立字符方向算文本主方向 [IsDigit()只是0-9] [2018/12/20/ 16:32:32 by aq_1000]
{
eCType = BaseDirection;
}
else
eCType = DirectionType.NEUTRAL;
}
else
eCType = ePre;
}
else
eCType = DirectionType.LTR;
return eCType;
}
// 是否括号
private static bool _IsBracket(char uc)
{
return (uc == ')' || uc == '(' || uc == '' || uc == '' ||
uc == ']' || uc == '[' || uc == '】' || uc == '【' ||
uc == '}' || uc == '{' ||
// uc == '≥' || uc == '≤' || uc == '>' || uc == '<' ||
uc == '》' || uc == '《' || uc == '“' || uc == '”' || uc == '"');
}
// 这些配对符,在从右至左排列中应该逆序显示
private static char _ProcessBracket(char uc)
{
if (uc == '[') return ']';
else if (uc == ']') return '[';
else if (uc == '【') return '】';
else if (uc == '】') return '【';
else if (uc == '{') return '}';
else if (uc == '}') return '{';
else if (uc == '(') return ')';
else if (uc == ')') return '(';
else if (uc == '') return '';
else if (uc == '') return '';
else if (uc == '<') return '>';
else if (uc == '>') return '<';
else if (uc == '《') return '》';
else if (uc == '》') return '《';
else if (uc == '≤') return '≥';
else if (uc == '≥') return '≤';
else if (uc == '”') return '“';
else if (uc == '”') return '“';
else return uc;
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 575b3af943ee8a04bb4d8feb568b1d2e
timeCreated: 1521600498
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,216 @@
using System.Collections.Generic;
using FairyGUI.Utils;
namespace FairyGUI
{
/// <summary>
///
/// </summary>
public class RichTextField : Container
{
/// <summary>
///
/// </summary>
public IHtmlPageContext htmlPageContext { get; set; }
/// <summary>
///
/// </summary>
public HtmlParseOptions htmlParseOptions { get; private set; }
/// <summary>
///
/// </summary>
public Dictionary<uint, Emoji> emojies { get; set; }
/// <summary>
///
/// </summary>
public TextField textField { get; private set; }
public RichTextField()
{
gameObject.name = "RichTextField";
this.opaque = true;
htmlPageContext = HtmlPageContext.inst;
htmlParseOptions = new HtmlParseOptions();
this.textField = new TextField();
textField.EnableRichSupport(this);
AddChild(textField);
}
/// <summary>
///
/// </summary>
virtual public string text
{
get { return textField.text; }
set { textField.text = value; }
}
/// <summary>
///
/// </summary>
virtual public string htmlText
{
get { return textField.htmlText; }
set { textField.htmlText = value; }
}
/// <summary>
///
/// </summary>
virtual public TextFormat textFormat
{
get { return textField.textFormat; }
set { textField.textFormat = value; }
}
/// <summary>
///
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public HtmlElement GetHtmlElement(string name)
{
List<HtmlElement> elements = textField.htmlElements;
int count = elements.Count;
for (int i = 0; i < count; i++)
{
HtmlElement element = elements[i];
if (name.Equals(element.name, System.StringComparison.OrdinalIgnoreCase))
return element;
}
return null;
}
/// <summary>
///
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public HtmlElement GetHtmlElementAt(int index)
{
return textField.htmlElements[index];
}
/// <summary>
///
/// </summary>
public int htmlElementCount
{
get { return textField.htmlElements.Count; }
}
/// <summary>
///
/// </summary>
/// <param name="index"></param>
/// <param name="show"></param>
public void ShowHtmlObject(int index, bool show)
{
HtmlElement element = textField.htmlElements[index];
if (element.htmlObject != null && element.type != HtmlElementType.Link)
{
//set hidden flag
if (show)
element.status &= 253; //~(1<<1)
else
element.status |= 2;
if ((element.status & 3) == 0) //not (hidden and clipped)
{
if ((element.status & 4) == 0) //not added
{
element.status |= 4;
element.htmlObject.Add();
}
}
else
{
if ((element.status & 4) != 0) //added
{
element.status &= 251;
element.htmlObject.Remove();
}
}
}
}
public override void EnsureSizeCorrect()
{
textField.EnsureSizeCorrect();
}
override protected void OnSizeChanged()
{
textField.size = _contentRect.size; //千万不可以调用this.size,后者会触发EnsureSizeCorrect
base.OnSizeChanged();
}
public override void Update(UpdateContext context)
{
textField.Redraw();
base.Update(context);
}
public override void Dispose()
{
if ((_flags & Flags.Disposed) != 0)
return;
CleanupObjects();
base.Dispose();
}
internal void CleanupObjects()
{
List<HtmlElement> elements = textField.htmlElements;
int count = elements.Count;
for (int i = 0; i < count; i++)
{
HtmlElement element = elements[i];
if (element.htmlObject != null)
{
element.htmlObject.Remove();
htmlPageContext.FreeObject(element.htmlObject);
}
}
}
virtual internal void RefreshObjects()
{
List<HtmlElement> elements = textField.htmlElements;
int count = elements.Count;
for (int i = 0; i < count; i++)
{
HtmlElement element = elements[i];
if (element.htmlObject != null)
{
if ((element.status & 3) == 0) //not (hidden and clipped)
{
if ((element.status & 4) == 0) //not added
{
element.status |= 4;
element.htmlObject.Add();
}
}
else
{
if ((element.status & 4) != 0) //added
{
element.status &= 251;
element.htmlObject.Remove();
}
}
}
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 87b472f7ce488fa4bbd8942342458ccf
timeCreated: 1460480288
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,94 @@
using System.Collections.Generic;
using UnityEngine;
using FairyGUI.Utils;
namespace FairyGUI
{
/// <summary>
///
/// </summary>
public class SelectionShape : DisplayObject, IMeshFactory
{
public readonly List<Rect> rects;
public SelectionShape()
{
CreateGameObject("SelectionShape");
graphics = new NGraphics(gameObject);
graphics.texture = NTexture.Empty;
graphics.meshFactory = this;
rects = new List<Rect>();
}
/// <summary>
///
/// </summary>
public Color color
{
get
{
return graphics.color;
}
set
{
graphics.color = value;
graphics.Tint();
}
}
public void Refresh()
{
int count = rects.Count;
if (count > 0)
{
Rect rect = new Rect();
rect = rects[0];
Rect tmp;
for (int i = 1; i < count; i++)
{
tmp = rects[i];
rect = ToolSet.Union(ref rect, ref tmp);
}
SetSize(rect.xMax, rect.yMax);
}
else
SetSize(0, 0);
graphics.SetMeshDirty();
}
public void Clear()
{
rects.Clear();
graphics.SetMeshDirty();
}
public void OnPopulateMesh(VertexBuffer vb)
{
int count = rects.Count;
if (count == 0 || this.color == Color.clear)
return;
for (int i = 0; i < count; i++)
vb.AddQuad(rects[i]);
vb.AddTriangles();
}
protected override DisplayObject HitTest()
{
Vector2 localPoint = WorldToLocal(HitTestContext.worldPoint, HitTestContext.direction);
if (_contentRect.Contains(localPoint))
{
int count = rects.Count;
for (int i = 0; i < count; i++)
{
if (rects[i].Contains(localPoint))
return this;
}
}
return null;
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 7f1920b8ccf9c8b4ca5f2794991735d9
timeCreated: 1535374214
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: d8a05d6d82201104cb6b5156ca294f54
timeCreated: 1535374215
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,175 @@
using UnityEngine;
namespace FairyGUI
{
/// <summary>
///
/// </summary>
public partial class TextFormat
{
public enum SpecialStyle
{
None,
Superscript,
Subscript
}
/// <summary>
///
/// </summary>
public int size;
/// <summary>
///
/// </summary>
public string font;
/// <summary>
///
/// </summary>
public Color color;
/// <summary>
///
/// </summary>
public int lineSpacing;
/// <summary>
///
/// </summary>
public int letterSpacing;
/// <summary>
///
/// </summary>
public bool bold;
/// <summary>
///
/// </summary>
public bool underline;
/// <summary>
///
/// </summary>
public bool italic;
/// <summary>
///
/// </summary>
public bool strikethrough;
/// <summary>
///
/// </summary>
public Color32[] gradientColor;
/// <summary>
///
/// </summary>
public AlignType align;
/// <summary>
///
/// </summary>
public SpecialStyle specialStyle;
/// <summary>
///
/// </summary>
public float outline;
/// <summary>
///
/// </summary>
public Color outlineColor;
/// <summary>
///
/// </summary>
public Vector2 shadowOffset;
/// <summary>
///
/// </summary>
public Color shadowColor;
public TextFormat()
{
color = Color.black;
size = 12;
lineSpacing = 3;
outlineColor = shadowColor = Color.black;
}
/// <summary>
///
/// </summary>
/// <param name="value"></param>
public void SetColor(uint value)
{
uint rr = (value >> 16) & 0x0000ff;
uint gg = (value >> 8) & 0x0000ff;
uint bb = value & 0x0000ff;
float r = rr / 255.0f;
float g = gg / 255.0f;
float b = bb / 255.0f;
color = new Color(r, g, b, 1);
}
/// <summary>
///
/// </summary>
/// <param name="aFormat"></param>
/// <returns></returns>
public bool EqualStyle(TextFormat aFormat)
{
return size == aFormat.size && color == aFormat.color
&& bold == aFormat.bold && underline == aFormat.underline
&& italic == aFormat.italic
&& strikethrough == aFormat.strikethrough
&& gradientColor == aFormat.gradientColor
&& align == aFormat.align
&& specialStyle == aFormat.specialStyle;
}
/// <summary>
/// Only base NOT all formats will be copied
/// </summary>
/// <param name="source"></param>
public void CopyFrom(TextFormat source)
{
this.size = source.size;
this.font = source.font;
this.color = source.color;
this.lineSpacing = source.lineSpacing;
this.letterSpacing = source.letterSpacing;
this.bold = source.bold;
this.underline = source.underline;
this.italic = source.italic;
this.strikethrough = source.strikethrough;
if (source.gradientColor != null)
{
this.gradientColor = new Color32[4];
source.gradientColor.CopyTo(this.gradientColor, 0);
}
else
this.gradientColor = null;
this.align = source.align;
this.specialStyle = source.specialStyle;
}
public void FillVertexColors(Color32[] vertexColors)
{
if (gradientColor == null)
vertexColors[0] = vertexColors[1] = vertexColors[2] = vertexColors[3] = color;
else
{
vertexColors[0] = gradientColor[1];
vertexColors[1] = gradientColor[0];
vertexColors[2] = gradientColor[2];
vertexColors[3] = gradientColor[3];
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: ecffbe294c108da4ab8a1c573e3d4dfd
timeCreated: 1460480288
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@
using UnityEngine;
namespace FairyGUI
{
/// <summary>
///
/// </summary>
public class TouchScreenKeyboard : IKeyboard
{
UnityEngine.TouchScreenKeyboard _keyboard;
public bool done
{
#if UNITY_2017_2_OR_NEWER
get
{
return _keyboard == null
|| _keyboard.status == UnityEngine.TouchScreenKeyboard.Status.Done
|| _keyboard.status == UnityEngine.TouchScreenKeyboard.Status.Canceled
|| _keyboard.status == UnityEngine.TouchScreenKeyboard.Status.LostFocus;
}
#else
get { return _keyboard == null || _keyboard.done || _keyboard.wasCanceled; }
#endif
}
public bool supportsCaret
{
get { return false; }
}
public string GetInput()
{
if (_keyboard != null)
{
string s = _keyboard.text;
if (this.done)
_keyboard = null;
return s;
}
else
return null;
}
public void Open(string text, bool autocorrection, bool multiline, bool secure, bool alert, string textPlaceholder, int keyboardType, bool hideInput)
{
if (_keyboard != null)
return;
UnityEngine.TouchScreenKeyboard.hideInput = hideInput;
_keyboard = UnityEngine.TouchScreenKeyboard.Open(text, (TouchScreenKeyboardType)keyboardType, autocorrection, multiline, secure, alert, textPlaceholder);
}
public void Close()
{
if (_keyboard != null)
{
_keyboard.active = false;
_keyboard = null;
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: cb24d1c92a1114a4f9db5688cc3fa35b
timeCreated: 1460480288
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,134 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FairyGUI
{
/// <summary>
/// 文字打字效果。先调用Start然后Print。
/// </summary>
public class TypingEffect
{
protected TextField _textField;
protected int _printIndex;
protected bool _started;
/// <summary>
///
/// </summary>
/// <param name="textField"></param>
public TypingEffect(TextField textField)
{
_textField = textField;
}
/// <summary>
///
/// </summary>
/// <param name="textField"></param>
public TypingEffect(GTextField textField)
{
if (textField is GRichTextField)
_textField = ((RichTextField)textField.displayObject).textField;
else
_textField = (TextField)textField.displayObject;
}
/// <summary>
/// 总输出次数
/// </summary>
public int totalTimes
{
get
{
int times = 0;
for (int i = 0; i < _textField.parsedText.Length; i++)
{
if (!char.IsWhiteSpace(_textField.parsedText[i]))
times++;
}
if (_textField.richTextField != null)
{
for (int i = 0; i < _textField.richTextField.htmlElementCount; i++)
{
if (_textField.richTextField.GetHtmlElementAt(i).isEntity)
times++;
}
}
return times;
}
}
/// <summary>
/// 开始打字效果。可以重复调用重复启动。
/// </summary>
public void Start()
{
if (_textField.SetTypingEffectPos(0) != -1)
{
_started = true;
_printIndex = 1;
//隐藏所有混排的对象
if (_textField.richTextField != null)
{
int ec = _textField.richTextField.htmlElementCount;
for (int i = 0; i < ec; i++)
_textField.richTextField.ShowHtmlObject(i, false);
}
}
else
_started = false;
}
/// <summary>
/// 输出一个字符。如果已经没有剩余的字符返回false。
/// </summary>
/// <returns></returns>
public bool Print()
{
if (!_started)
return false;
_printIndex = _textField.SetTypingEffectPos(_printIndex);
if (_printIndex != -1)
return true;
else
{
_started = false;
return false;
}
}
/// <summary>
/// 打印的协程。
/// </summary>
/// <param name="interval">每个字符输出的时间间隔</param>
/// <returns></returns>
public IEnumerator Print(float interval)
{
while (Print())
yield return new WaitForSeconds(interval);
}
/// <summary>
/// 使用固定时间间隔完成整个打印过程。
/// </summary>
/// <param name="interval"></param>
public void PrintAll(float interval)
{
Timers.inst.StartCoroutine(Print(interval));
}
public void Cancel()
{
if (!_started)
return;
_started = false;
_textField.SetTypingEffectPos(-1);
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 213be0a4bfae47c4ebf643f5ee856399
timeCreated: 1535374214
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: