UILable添加预定义字体样式选项
作者:追风剑情 发布于:2017-8-22 14:34 分类:NGUI
NGUI-3.8
一、修改UILabel.cs
//------------------------------------------------- // NGUI: Next-Gen UI kit // Copyright © 2011-2017 Tasharen Entertainment Inc //------------------------------------------------- using UnityEngine; using System.Collections.Generic; using System; using Alignment = NGUIText.Alignment; #if UNITY_EDITOR using System.IO; using LitJson; #endif [ExecuteInEditMode] [AddComponentMenu("NGUI/UI/NGUI Label")] public class UILabel : UIWidget { public enum Effect { None, Shadow, Outline, Outline8, } public enum Overflow { ShrinkContent, ClampContent, ResizeFreely, ResizeHeight, } public enum Crispness { Never, OnDesktop, Always, } public enum Modifier { None, ToUppercase, ToLowercase, Custom = 255, } /// <summary> /// Whether the label will keep its content crisp even when shrunk. /// You may want to turn this off on mobile devices. /// </summary> public Crispness keepCrispWhenShrunk = Crispness.OnDesktop; [HideInInspector][SerializeField] Font mTrueTypeFont; [HideInInspector][SerializeField] UIFont mFont; #if !UNITY_3_5 [MultilineAttribute(6)] #endif [HideInInspector][SerializeField] string mText = ""; [HideInInspector][SerializeField] int mFontSize = 16; [HideInInspector][SerializeField] FontStyle mFontStyle = FontStyle.Normal; [HideInInspector][SerializeField] Alignment mAlignment = Alignment.Automatic; [HideInInspector][SerializeField] bool mEncoding = true; [HideInInspector][SerializeField] int mMaxLineCount = 0; // 0 denotes unlimited [HideInInspector][SerializeField] Effect mEffectStyle = Effect.None; [HideInInspector][SerializeField] Color mEffectColor = Color.black; [HideInInspector][SerializeField] NGUIText.SymbolStyle mSymbols = NGUIText.SymbolStyle.Normal; [HideInInspector][SerializeField] Vector2 mEffectDistance = Vector2.one; [HideInInspector][SerializeField] Overflow mOverflow = Overflow.ShrinkContent; [HideInInspector][SerializeField] bool mApplyGradient = false; [HideInInspector][SerializeField] Color mGradientTop = Color.white; [HideInInspector][SerializeField] Color mGradientBottom = new Color(0.7f, 0.7f, 0.7f); [HideInInspector][SerializeField] int mSpacingX = 0; [HideInInspector][SerializeField] int mSpacingY = 0; [HideInInspector][SerializeField] bool mUseFloatSpacing = false; [HideInInspector][SerializeField] float mFloatSpacingX = 0; [HideInInspector][SerializeField] float mFloatSpacingY = 0; [HideInInspector][SerializeField] bool mOverflowEllipsis = false; [HideInInspector][SerializeField] int mOverflowWidth = 0; [HideInInspector][SerializeField] Modifier mModifier = Modifier.None; // Obsolete values [HideInInspector][SerializeField] bool mShrinkToFit = false; [HideInInspector][SerializeField] int mMaxLineWidth = 0; [HideInInspector][SerializeField] int mMaxLineHeight = 0; [HideInInspector][SerializeField] float mLineWidth = 0; [HideInInspector][SerializeField] bool mMultiline = true; [System.NonSerialized] Font mActiveTTF = null; [System.NonSerialized] float mDensity = 1f; [System.NonSerialized] bool mShouldBeProcessed = true; [System.NonSerialized] string mProcessedText = null; [System.NonSerialized] bool mPremultiply = false; [System.NonSerialized] Vector2 mCalculatedSize = Vector2.zero; [System.NonSerialized] float mScale = 1f; [System.NonSerialized] int mFinalFontSize = 0; [System.NonSerialized] int mLastWidth = 0; [System.NonSerialized] int mLastHeight = 0; /// <summary> /// Font size after modifications got taken into consideration such as shrinking content. /// </summary> public int finalFontSize { get { if (trueTypeFont) return Mathf.RoundToInt(mScale * mFinalFontSize); return Mathf.RoundToInt(mFinalFontSize * mScale); } } /// <summary> /// Function used to determine if something has changed (and thus the geometry must be rebuilt) /// </summary> bool shouldBeProcessed { get { return mShouldBeProcessed; } set { if (value) { mChanged = true; mShouldBeProcessed = true; } else { mShouldBeProcessed = false; } } } /// <summary> /// Whether the rectangle is anchored horizontally. /// </summary> public override bool isAnchoredHorizontally { get { return base.isAnchoredHorizontally || mOverflow == Overflow.ResizeFreely; } } /// <summary> /// Whether the rectangle is anchored vertically. /// </summary> public override bool isAnchoredVertically { get { return base.isAnchoredVertically || mOverflow == Overflow.ResizeFreely || mOverflow == Overflow.ResizeHeight; } } /// <summary> /// Retrieve the material used by the font. /// </summary> public override Material material { get { if (mMat != null) return mMat; if (mFont != null) return mFont.material; if (mTrueTypeFont != null) return mTrueTypeFont.material; return null; } set { base.material = value; } } /// <summary> /// Label's main texture comes from the font itself. /// </summary> public override Texture mainTexture { get { if (mFont != null) return mFont.texture; if (mTrueTypeFont != null) { var mat = mTrueTypeFont.material; if (mat != null) return mat.mainTexture; } return null; } set { base.mainTexture = value; } } [Obsolete("Use UILabel.bitmapFont instead")] public UIFont font { get { return bitmapFont; } set { bitmapFont = value; } } /// <summary> /// Set the font used by this label. /// </summary> public UIFont bitmapFont { get { return mFont; } set { if (mFont != value) { RemoveFromPanel(); mFont = value; mTrueTypeFont = null; MarkAsChanged(); } } } /// <summary> /// Set the font used by this label. /// </summary> public Font trueTypeFont { get { if (mTrueTypeFont != null) return mTrueTypeFont; return (mFont != null ? mFont.dynamicFont : null); } set { if (mTrueTypeFont != value) { SetActiveFont(null); RemoveFromPanel(); mTrueTypeFont = value; shouldBeProcessed = true; mFont = null; SetActiveFont(value); ProcessAndRequest(); if (mActiveTTF != null) base.MarkAsChanged(); } } } /// <summary> /// Ambiguous helper function. /// </summary> public UnityEngine.Object ambigiousFont { get { return (UnityEngine.Object)mFont ?? (UnityEngine.Object)mTrueTypeFont; } set { UIFont bf = value as UIFont; if (bf != null) bitmapFont = bf; else trueTypeFont = value as Font; } } /// <summary> /// Text that's being displayed by the label. /// </summary> public string text { get { return mText; } set { if (mText == value) return; if (string.IsNullOrEmpty(value)) { if (!string.IsNullOrEmpty(mText)) { mText = ""; MarkAsChanged(); ProcessAndRequest(); } } else if (mText != value) { mText = value; MarkAsChanged(); ProcessAndRequest(); } if (autoResizeBoxCollider) ResizeCollider(); } } /// <summary> /// Default font size. /// </summary> public int defaultFontSize { get { return (trueTypeFont != null) ? mFontSize : (mFont != null ? mFont.defaultSize : 16); } } /// <summary> /// Active font size used by the label. /// </summary> public int fontSize { get { return mFontSize; } set { value = Mathf.Clamp(value, 0, 256); if (mFontSize != value) { mFontSize = value; shouldBeProcessed = true; ProcessAndRequest(); } } } /// <summary> /// Dynamic font style used by the label. /// </summary> public FontStyle fontStyle { get { return mFontStyle; } set { if (mFontStyle != value) { mFontStyle = value; shouldBeProcessed = true; ProcessAndRequest(); } } } /// <summary> /// Text alignment option. /// </summary> public Alignment alignment { get { return mAlignment; } set { if (mAlignment != value) { mAlignment = value; shouldBeProcessed = true; ProcessAndRequest(); } } } /// <summary> /// Whether a gradient will be applied. /// </summary> public bool applyGradient { get { return mApplyGradient; } set { if (mApplyGradient != value) { mApplyGradient = value; MarkAsChanged(); } } } /// <summary> /// Top gradient color. /// </summary> public Color gradientTop { get { return mGradientTop; } set { if (mGradientTop != value) { mGradientTop = value; if (mApplyGradient) MarkAsChanged(); } } } /// <summary> /// Bottom gradient color. /// </summary> public Color gradientBottom { get { return mGradientBottom; } set { if (mGradientBottom != value) { mGradientBottom = value; if (mApplyGradient) MarkAsChanged(); } } } /// <summary> /// Additional horizontal spacing between characters when printing text. /// </summary> public int spacingX { get { return mSpacingX; } set { if (mSpacingX != value) { mSpacingX = value; MarkAsChanged(); } } } /// <summary> /// Additional vertical spacing between lines when printing text. /// </summary> public int spacingY { get { return mSpacingY; } set { if (mSpacingY != value) { mSpacingY = value; MarkAsChanged(); } } } /// <summary> /// Whether this label will use float text spacing values, instead of integers. /// </summary> public bool useFloatSpacing { get { return mUseFloatSpacing; } set { if (mUseFloatSpacing != value) { mUseFloatSpacing = value; shouldBeProcessed = true; } } } /// <summary> /// Additional horizontal spacing between characters when printing text. /// For this to have any effect useFloatSpacing must be true. /// </summary> public float floatSpacingX { get { return mFloatSpacingX; } set { if (!Mathf.Approximately(mFloatSpacingX, value)) { mFloatSpacingX = value; MarkAsChanged(); } } } /// <summary> /// Additional vertical spacing between lines when printing text. /// For this to have any effect useFloatSpacing must be true. /// </summary> public float floatSpacingY { get { return mFloatSpacingY; } set { if (!Mathf.Approximately(mFloatSpacingY, value)) { mFloatSpacingY = value; MarkAsChanged(); } } } /// <summary> /// Convenience property to get the used y spacing. /// </summary> public float effectiveSpacingY { get { return mUseFloatSpacing ? mFloatSpacingY : mSpacingY; } } /// <summary> /// Convenience property to get the used x spacing. /// </summary> public float effectiveSpacingX { get { return mUseFloatSpacing ? mFloatSpacingX : mSpacingX; } } /// <summary> /// Whether to append "..." at the end of clamped text that didn't fit. /// </summary> public bool overflowEllipsis { get { return mOverflowEllipsis; } set { if (mOverflowEllipsis != value) { mOverflowEllipsis = value; MarkAsChanged(); } } } /// <summary> /// Maximum width used when Resize Freely overflow type is enabled. /// If the printed text exceeds this width, it will wrap onto the following line. /// </summary> public int overflowWidth { get { return mOverflowWidth; } set { if (mOverflowWidth != value) { mOverflowWidth = value; MarkAsChanged(); } } } /// <summary> /// Whether the label will use the printed size instead of font size when printing the label. /// It's a dynamic font feature that will ensure that the text is crisp when shrunk. /// </summary> bool keepCrisp { get { if (trueTypeFont != null && keepCrispWhenShrunk != Crispness.Never) { #if UNITY_IPHONE || UNITY_ANDROID || UNITY_WP8 || UNITY_WP_8_1 || UNITY_BLACKBERRY return (keepCrispWhenShrunk == Crispness.Always); #else return true; #endif } return false; } } /// <summary> /// Whether this label will support color encoding in the format of [RRGGBB] and new line in the form of a "\\n" string. /// </summary> public bool supportEncoding { get { return mEncoding; } set { if (mEncoding != value) { mEncoding = value; shouldBeProcessed = true; } } } /// <summary> /// Style used for symbols. /// </summary> public NGUIText.SymbolStyle symbolStyle { get { return mSymbols; } set { if (mSymbols != value) { mSymbols = value; shouldBeProcessed = true; } } } /// <summary> /// Overflow method controls the label's behaviour when its content doesn't fit the bounds. /// </summary> public Overflow overflowMethod { get { return mOverflow; } set { if (mOverflow != value) { mOverflow = value; shouldBeProcessed = true; } } } /// <summary> /// Maximum width of the label in pixels. /// </summary> [System.Obsolete("Use 'width' instead")] public int lineWidth { get { return width; } set { width = value; } } /// <summary> /// Maximum height of the label in pixels. /// </summary> [System.Obsolete("Use 'height' instead")] public int lineHeight { get { return height; } set { height = value; } } /// <summary> /// Whether the label supports multiple lines. /// </summary> public bool multiLine { get { return mMaxLineCount != 1; } set { if ((mMaxLineCount != 1) != value) { mMaxLineCount = (value ? 0 : 1); shouldBeProcessed = true; } } } /// <summary> /// Process the label's text before returning its corners. /// </summary> public override Vector3[] localCorners { get { if (shouldBeProcessed) ProcessText(); return base.localCorners; } } /// <summary> /// Process the label's text before returning its corners. /// </summary> public override Vector3[] worldCorners { get { if (shouldBeProcessed) ProcessText(); return base.worldCorners; } } /// <summary> /// Process the label's text before returning its drawing dimensions. /// </summary> public override Vector4 drawingDimensions { get { if (shouldBeProcessed) ProcessText(); return base.drawingDimensions; } } /// <summary> /// The max number of lines to be displayed for the label /// </summary> public int maxLineCount { get { return mMaxLineCount; } set { if (mMaxLineCount != value) { mMaxLineCount = Mathf.Max(value, 0); shouldBeProcessed = true; if (overflowMethod == Overflow.ShrinkContent) MakePixelPerfect(); } } } /// <summary> /// What effect is used by the label. /// </summary> public Effect effectStyle { get { return mEffectStyle; } set { if (mEffectStyle != value) { mEffectStyle = value; shouldBeProcessed = true; } } } /// <summary> /// Color used by the effect, if it's enabled. /// </summary> public Color effectColor { get { return mEffectColor; } set { if (mEffectColor != value) { mEffectColor = value; if (mEffectStyle != Effect.None) shouldBeProcessed = true; } } } /// <summary> /// Effect distance in pixels. /// </summary> public Vector2 effectDistance { get { return mEffectDistance; } set { if (mEffectDistance != value) { mEffectDistance = value; shouldBeProcessed = true; } } } /// <summary> /// How many quads there are per printed character. /// </summary> public int quadsPerCharacter { get { if (mEffectStyle == Effect.Shadow) return 2; else if (mEffectStyle == Effect.Outline) return 5; else if (mEffectStyle == Effect.Outline8) return 9; return 1; } } /// <summary> /// Whether the label will automatically shrink its size in order to fit the maximum line width. /// </summary> [System.Obsolete("Use 'overflowMethod == UILabel.Overflow.ShrinkContent' instead")] public bool shrinkToFit { get { return mOverflow == Overflow.ShrinkContent; } set { if (value) { overflowMethod = Overflow.ShrinkContent; } } } /// <summary> /// Returns the processed version of 'text', with new line characters, line wrapping, etc. /// </summary> public string processedText { get { if (mLastWidth != mWidth || mLastHeight != mHeight) { mLastWidth = mWidth; mLastHeight = mHeight; mShouldBeProcessed = true; } // Process the text if necessary if (shouldBeProcessed) ProcessText(); return mProcessedText; } } /// <summary> /// Actual printed size of the text, in pixels. /// </summary> public Vector2 printedSize { get { if (shouldBeProcessed) ProcessText(); return mCalculatedSize; } } /// <summary> /// Local size of the widget, in pixels. /// </summary> public override Vector2 localSize { get { if (shouldBeProcessed) ProcessText(); return base.localSize; } } /// <summary> /// Whether the label has a valid font. /// </summary> bool isValid { get { return mFont != null || mTrueTypeFont != null; } } /// <summary> /// Custom text modifier that can transform the visible text when the label's text is assigned. /// </summary> public ModifierFunc customModifier; public delegate string ModifierFunc (string s); /// <summary> /// Text modifier can transform the text that's actually printed, without altering the label's text value. /// </summary> public Modifier modifier { get { return mModifier; } set { if (mModifier != value) { mModifier = value; MarkAsChanged(); ProcessAndRequest(); } } } static BetterList<UILabel> mList = new BetterList<UILabel>(); static Dictionary<Font, int> mFontUsage = new Dictionary<Font, int>(); /// <summary> /// Register the font texture change listener. /// </summary> protected override void OnInit () { base.OnInit(); mList.Add(this); SetActiveFont(trueTypeFont); } /// <summary> /// Remove the font texture change listener. /// </summary> protected override void OnDisable () { SetActiveFont(null); mList.Remove(this); base.OnDisable(); } /// <summary> /// Set the active font, correctly setting and clearing callbacks. /// </summary> protected void SetActiveFont (Font fnt) { if (mActiveTTF != fnt) { Font font = mActiveTTF; if (font != null) { int usage; if (mFontUsage.TryGetValue(font, out usage)) { usage = Mathf.Max(0, --usage); if (usage == 0) { #if UNITY_4_3 || UNITY_4_5 font.textureRebuildCallback = null; #endif mFontUsage.Remove(font); } else mFontUsage[font] = usage; } #if UNITY_4_3 || UNITY_4_5 else font.textureRebuildCallback = null; #endif } mActiveTTF = fnt; font = fnt; if (font != null) { int usage = 0; // Font hasn't been used yet? Register a change delegate callback #if UNITY_4_3 || UNITY_4_5 if (!mFontUsage.TryGetValue(font, out usage)) font.textureRebuildCallback = delegate() { OnFontChanged(font); }; #endif #if UNITY_FLASH mFontUsage[font] = usage + 1; #else mFontUsage[font] = ++usage; #endif } } } /// <summary> /// Label's actual printed text may be modified before being drawn. /// </summary> public string printedText { get { if (!string.IsNullOrEmpty(mText)) { if (mModifier == Modifier.None) return mText; if (mModifier == Modifier.ToLowercase) return mText.ToLower(); if (mModifier == Modifier.ToUppercase) return mText.ToUpper(); if (mModifier == Modifier.Custom && customModifier != null) return customModifier(mText); } return mText; } } /// <summary> /// Notification called when the Unity's font's texture gets rebuilt. /// Unity's font has a nice tendency to simply discard other characters when the texture's dimensions change. /// By requesting them inside the notification callback, we immediately force them back in. /// Originally I was subscribing each label to the font individually, but as it turned out /// mono's delegate system causes an insane amount of memory allocations when += or -= to a delegate. /// So... queue yet another work-around. /// </summary> static void OnFontChanged (Font font) { for (int i = 0; i < mList.size; ++i) { UILabel lbl = mList[i]; if (lbl != null) { Font fnt = lbl.trueTypeFont; if (fnt == font) { fnt.RequestCharactersInTexture(lbl.mText, lbl.mFinalFontSize, lbl.mFontStyle); lbl.MarkAsChanged(); if (lbl.panel == null) lbl.CreatePanel(); if (mTempDrawcalls == null) mTempDrawcalls = new BetterList<UIDrawCall>(); if (lbl.drawCall != null && !mTempDrawcalls.Contains(lbl.drawCall)) mTempDrawcalls.Add(lbl.drawCall); } } } if (mTempDrawcalls != null) { for (int i = 0, imax = mTempDrawcalls.size; i < imax; ++i) { UIDrawCall dc = mTempDrawcalls[i]; if (dc.panel != null) dc.panel.FillDrawCall(dc); } mTempDrawcalls.Clear(); } // http://www.tasharen.com/forum/index.php?topic=15202.0 /*++mFontChangedDepth; for (int i = 0; i < mList.size; ++i) { UILabel lbl = mList[i]; if (lbl != null)v [kp;' 5rfc328i0u { Font fnt = lbl.trueTypeFont; if (fnt == font) { if (mTempLabels == null) mTempLabels = new BetterList<UILabel>(); if (!mTempLabels.Contains(lbl)) { mTempLabels.Add(lbl); lbl.UpdateNGUIText(); fnt.RequestCharactersInTexture(lbl.printedText, lbl.mFinalFontSize, lbl.mFontStyle); } } } } if (mFontChangedDepth == 1 && mTempLabels != null) { var frame = Time.frameCount; for (int i = 0, imax = mTempLabels.size; i < imax; ++i) { var lbl = mTempLabels.buffer[i]; if (lbl.panel == null) lbl.CreatePanel(); lbl.MarkAsChanged(); lbl.UpdateGeometry(frame); var dc = lbl.drawCall; if (dc != null) { if (mTempDrawcalls == null) mTempDrawcalls = new BetterList<UIDrawCall>(); if (!mTempDrawcalls.Contains(dc)) mTempDrawcalls.Add(dc); } } mTempLabels.Clear(); if (mTempDrawcalls != null) { for (int i = 0, imax = mTempDrawcalls.size; i < imax; ++i) { var dc = mTempDrawcalls.buffer[i]; if (dc.panel != null) dc.panel.FillDrawCall(dc); } mTempDrawcalls.Clear(); } } --mFontChangedDepth;*/ } //[System.NonSerialized] static int mFontChangedDepth = 0; [System.NonSerialized] static BetterList<UIDrawCall> mTempDrawcalls; //[System.NonSerialized] static BetterList<UILabel> mTempLabels; /// <summary> /// Get the sides of the rectangle relative to the specified transform. /// The order is left, top, right, bottom. /// </summary> public override Vector3[] GetSides (Transform relativeTo) { if (shouldBeProcessed) ProcessText(); return base.GetSides(relativeTo); } /// <summary> /// Upgrading labels is a bit different. /// </summary> protected override void UpgradeFrom265 () { ProcessText(true, true); if (mShrinkToFit) { overflowMethod = Overflow.ShrinkContent; mMaxLineCount = 0; } if (mMaxLineWidth != 0) { width = mMaxLineWidth; overflowMethod = mMaxLineCount > 0 ? Overflow.ResizeHeight : Overflow.ShrinkContent; } else overflowMethod = Overflow.ResizeFreely; if (mMaxLineHeight != 0) height = mMaxLineHeight; if (mFont != null) { int min = mFont.defaultSize; if (height < min) height = min; fontSize = min; } mMaxLineWidth = 0; mMaxLineHeight = 0; mShrinkToFit = false; NGUITools.UpdateWidgetCollider(gameObject, true); } /// <summary> /// If the label is anchored it should not auto-resize. /// </summary> protected override void OnAnchor () { if (mOverflow == Overflow.ResizeFreely) { if (isFullyAnchored) mOverflow = Overflow.ShrinkContent; } else if (mOverflow == Overflow.ResizeHeight) { if (topAnchor.target != null && bottomAnchor.target != null) mOverflow = Overflow.ShrinkContent; } base.OnAnchor(); } /// <summary> /// Request the needed characters in the texture. /// </summary> void ProcessAndRequest () { #if UNITY_EDITOR if (!Application.isPlaying && !NGUITools.GetActive(this)) return; if (!mAllowProcessing) return; #endif if (ambigiousFont != null) ProcessText(); } #if UNITY_EDITOR // Used to ensure that we don't process font more than once inside OnValidate function below [System.NonSerialized] bool mAllowProcessing = true; [System.NonSerialized] bool mUsingTTF = true; /// <summary> /// Validate the properties. /// </summary> protected override void OnValidate () { base.OnValidate(); if (NGUITools.GetActive(this)) { Font ttf = mTrueTypeFont; UIFont fnt = mFont; // If the true type font was not used before, but now it is, clear the font reference if (!mUsingTTF && ttf != null) fnt = null; else if (mUsingTTF && fnt != null) ttf = null; mFont = null; mTrueTypeFont = null; mAllowProcessing = false; SetActiveFont(null); if (fnt != null) { bitmapFont = fnt; mUsingTTF = false; } else if (ttf != null) { trueTypeFont = ttf; mUsingTTF = true; } shouldBeProcessed = true; mAllowProcessing = true; ProcessAndRequest(); if (autoResizeBoxCollider) ResizeCollider(); } } #endif #if !UNITY_4_3 && !UNITY_4_5 static bool mTexRebuildAdded = false; protected override void OnEnable () { base.OnEnable(); if (!mTexRebuildAdded) { mTexRebuildAdded = true; Font.textureRebuilt += OnFontChanged; } } #endif /// <summary> /// Determine start-up values. /// </summary> protected override void OnStart () { base.OnStart(); // Legacy support if (mLineWidth > 0f) { mMaxLineWidth = Mathf.RoundToInt(mLineWidth); mLineWidth = 0f; } if (!mMultiline) { mMaxLineCount = 1; mMultiline = true; } // Whether this is a premultiplied alpha shader mPremultiply = (material != null && material.shader != null && material.shader.name.Contains("Premultiplied")); // Request the text within the font ProcessAndRequest(); } /// <summary> /// UILabel needs additional processing when something changes. /// </summary> public override void MarkAsChanged () { shouldBeProcessed = true; base.MarkAsChanged(); } /// <summary> /// Process the raw text, called when something changes. /// </summary> public void ProcessText (bool legacyMode = false, bool full = true) { if (!isValid) return; mChanged = true; shouldBeProcessed = false; float regionX = mDrawRegion.z - mDrawRegion.x; float regionY = mDrawRegion.w - mDrawRegion.y; NGUIText.rectWidth = legacyMode ? (mMaxLineWidth != 0 ? mMaxLineWidth : 1000000) : width; NGUIText.rectHeight = legacyMode ? (mMaxLineHeight != 0 ? mMaxLineHeight : 1000000) : height; NGUIText.regionWidth = (regionX != 1f) ? Mathf.RoundToInt(NGUIText.rectWidth * regionX) : NGUIText.rectWidth; NGUIText.regionHeight = (regionY != 1f) ? Mathf.RoundToInt(NGUIText.rectHeight * regionY) : NGUIText.rectHeight; mFinalFontSize = Mathf.Abs(legacyMode ? Mathf.RoundToInt(cachedTransform.localScale.x) : defaultFontSize); mScale = 1f; if (NGUIText.regionWidth < 1 || NGUIText.regionHeight < 0) { mProcessedText = ""; return; } bool isDynamic = (trueTypeFont != null); if (isDynamic && keepCrisp) { UIRoot rt = root; if (rt != null) mDensity = (rt != null) ? rt.pixelSizeAdjustment : 1f; } else mDensity = 1f; if (full) UpdateNGUIText(); if (mOverflow == Overflow.ResizeFreely) { NGUIText.rectWidth = 1000000; NGUIText.regionWidth = 1000000; if (mOverflowWidth > 0) { NGUIText.rectWidth = Mathf.Min(NGUIText.rectWidth, mOverflowWidth); NGUIText.regionWidth = Mathf.Min(NGUIText.regionWidth, mOverflowWidth); } } if (mOverflow == Overflow.ResizeFreely || mOverflow == Overflow.ResizeHeight) { NGUIText.rectHeight = 1000000; NGUIText.regionHeight = 1000000; } if (mFinalFontSize > 0) { bool adjustSize = keepCrisp; for (int ps = mFinalFontSize; ps > 0; --ps) { // Adjust either the size, or the scale if (adjustSize) { mFinalFontSize = ps; NGUIText.fontSize = mFinalFontSize; } else { mScale = (float)ps / mFinalFontSize; NGUIText.fontScale = isDynamic ? mScale : ((float)mFontSize / mFont.defaultSize) * mScale; } NGUIText.Update(false); // Wrap the text bool fits = NGUIText.WrapText(printedText, out mProcessedText, false, false, mOverflow == Overflow.ClampContent && mOverflowEllipsis); if (mOverflow == Overflow.ShrinkContent && !fits) { if (--ps > 1) continue; else break; } else if (mOverflow == Overflow.ResizeFreely) { mCalculatedSize = NGUIText.CalculatePrintedSize(mProcessedText); int w = Mathf.Max(minWidth, Mathf.RoundToInt(mCalculatedSize.x)); if (regionX != 1f) w = Mathf.RoundToInt(w / regionX); int h = Mathf.Max(minHeight, Mathf.RoundToInt(mCalculatedSize.y)); if (regionY != 1f) h = Mathf.RoundToInt(h / regionY); if ((w & 1) == 1) ++w; if ((h & 1) == 1) ++h; if (mWidth != w || mHeight != h) { mWidth = w; mHeight = h; if (onChange != null) onChange(); } } else if (mOverflow == Overflow.ResizeHeight) { mCalculatedSize = NGUIText.CalculatePrintedSize(mProcessedText); int h = Mathf.Max(minHeight, Mathf.RoundToInt(mCalculatedSize.y)); if (regionY != 1f) h = Mathf.RoundToInt(h / regionY); if ((h & 1) == 1) ++h; if (mHeight != h) { mHeight = h; if (onChange != null) onChange(); } } else { mCalculatedSize = NGUIText.CalculatePrintedSize(mProcessedText); } // Upgrade to the new system if (legacyMode) { width = Mathf.RoundToInt(mCalculatedSize.x); height = Mathf.RoundToInt(mCalculatedSize.y); cachedTransform.localScale = Vector3.one; } break; } } else { cachedTransform.localScale = Vector3.one; mProcessedText = ""; mScale = 1f; } if (full) { NGUIText.bitmapFont = null; NGUIText.dynamicFont = null; } } /// <summary> /// Text is pixel-perfect when its scale matches the size. /// </summary> public override void MakePixelPerfect () { if (ambigiousFont != null) { Vector3 pos = cachedTransform.localPosition; pos.x = Mathf.RoundToInt(pos.x); pos.y = Mathf.RoundToInt(pos.y); pos.z = Mathf.RoundToInt(pos.z); cachedTransform.localPosition = pos; cachedTransform.localScale = Vector3.one; if (mOverflow == Overflow.ResizeFreely) { AssumeNaturalSize(); } else { int w = width; int h = height; Overflow over = mOverflow; if (over != Overflow.ResizeHeight) mWidth = 100000; mHeight = 100000; mOverflow = Overflow.ShrinkContent; ProcessText(false, true); mOverflow = over; int minX = Mathf.RoundToInt(mCalculatedSize.x); int minY = Mathf.RoundToInt(mCalculatedSize.y); minX = Mathf.Max(minX, base.minWidth); minY = Mathf.Max(minY, base.minHeight); if ((minX & 1) == 1) ++minX; if ((minY & 1) == 1) ++minY; mWidth = Mathf.Max(w, minX); mHeight = Mathf.Max(h, minY); MarkAsChanged(); } } else base.MakePixelPerfect(); } /// <summary> /// Make the label assume its natural size. /// </summary> public void AssumeNaturalSize () { if (ambigiousFont != null) { mWidth = 100000; mHeight = 100000; ProcessText(false, true); mWidth = Mathf.RoundToInt(mCalculatedSize.x); mHeight = Mathf.RoundToInt(mCalculatedSize.y); if ((mWidth & 1) == 1) ++mWidth; if ((mHeight & 1) == 1) ++mHeight; MarkAsChanged(); } } [System.Obsolete("Use UILabel.GetCharacterAtPosition instead")] public int GetCharacterIndex (Vector3 worldPos) { return GetCharacterIndexAtPosition(worldPos, false); } [System.Obsolete("Use UILabel.GetCharacterAtPosition instead")] public int GetCharacterIndex (Vector2 localPos) { return GetCharacterIndexAtPosition(localPos, false); } static List<Vector3> mTempVerts = new List<Vector3>(); static List<int> mTempIndices = new List<int>(); /// <summary> /// Return the index of the character at the specified world position. /// </summary> public int GetCharacterIndexAtPosition (Vector3 worldPos, bool precise) { Vector2 localPos = cachedTransform.InverseTransformPoint(worldPos); return GetCharacterIndexAtPosition(localPos, precise); } /// <summary> /// Return the index of the character at the specified local position. /// </summary> public int GetCharacterIndexAtPosition (Vector2 localPos, bool precise) { if (isValid) { string text = processedText; if (string.IsNullOrEmpty(text)) return 0; UpdateNGUIText(); if (precise) NGUIText.PrintExactCharacterPositions(text, mTempVerts, mTempIndices); else NGUIText.PrintApproximateCharacterPositions(text, mTempVerts, mTempIndices); if (mTempVerts.Count > 0) { ApplyOffset(mTempVerts, 0); int retVal = precise ? NGUIText.GetExactCharacterIndex(mTempVerts, mTempIndices, localPos) : NGUIText.GetApproximateCharacterIndex(mTempVerts, mTempIndices, localPos); mTempVerts.Clear(); mTempIndices.Clear(); NGUIText.bitmapFont = null; NGUIText.dynamicFont = null; return retVal; } NGUIText.bitmapFont = null; NGUIText.dynamicFont = null; } return 0; } /// <summary> /// Retrieve the word directly below the specified world-space position. /// </summary> public string GetWordAtPosition (Vector3 worldPos) { int index = GetCharacterIndexAtPosition(worldPos, true); return GetWordAtCharacterIndex(index); } /// <summary> /// Retrieve the word directly below the specified relative-to-label position. /// </summary> public string GetWordAtPosition (Vector2 localPos) { int index = GetCharacterIndexAtPosition(localPos, true); return GetWordAtCharacterIndex(index); } /// <summary> /// Retrieve the word right under the specified character index. /// </summary> public string GetWordAtCharacterIndex (int characterIndex) { string s = printedText; if (characterIndex != -1 && characterIndex < s.Length) { #if UNITY_FLASH int wordStart = LastIndexOfAny(s, new char[] { ' ', '\n' }, characterIndex) + 1; int wordEnd = IndexOfAny(s, new char[] { ' ', '\n', ',', '.' }, characterIndex); #else int wordStart = s.LastIndexOfAny(new char[] {' ', '\n'}, characterIndex) + 1; int wordEnd = s.IndexOfAny(new char[] { ' ', '\n', ',', '.' }, characterIndex); #endif if (wordEnd == -1) wordEnd = s.Length; if (wordStart != wordEnd) { int len = wordEnd - wordStart; if (len > 0) { string word = s.Substring(wordStart, len); return NGUIText.StripSymbols(word); } } } return null; } #if UNITY_FLASH /// <summary> /// Flash is fail IRL: http://www.tasharen.com/forum/index.php?topic=11390.0 /// </summary> int LastIndexOfAny (string input, char[] any, int start) { if (start >= 0 && input.Length > 0 && any.Length > 0 && start < input.Length) { for (int w = start; w >= 0; w--) { for (int r = 0; r < any.Length; r++) { if (any[r] == input[w]) { return w; } } } } return -1; } /// <summary> /// Flash is fail IRL: http://www.tasharen.com/forum/index.php?topic=11390.0 /// </summary> int IndexOfAny (string input, char[] any, int start) { if (start >= 0 && input.Length > 0 && any.Length > 0 && start < input.Length) { for (int w = start; w < input.Length; w++) { for (int r = 0; r < any.Length; r++) { if (any[r] == input[w]) { return w; } } } } return -1; } #endif /// <summary> /// Retrieve the URL directly below the specified world-space position. /// </summary> public string GetUrlAtPosition (Vector3 worldPos) { return GetUrlAtCharacterIndex(GetCharacterIndexAtPosition(worldPos, true)); } /// <summary> /// Retrieve the URL directly below the specified relative-to-label position. /// </summary> public string GetUrlAtPosition (Vector2 localPos) { return GetUrlAtCharacterIndex(GetCharacterIndexAtPosition(localPos, true)); } /// <summary> /// Retrieve the URL right under the specified character index. /// </summary> public string GetUrlAtCharacterIndex (int characterIndex) { string s = printedText; if (characterIndex != -1 && characterIndex < s.Length - 6) { int linkStart; // LastIndexOf() fails if the string happens to begin with the expected text if (s[characterIndex] == '[' && s[characterIndex + 1] == 'u' && s[characterIndex + 2] == 'r' && s[characterIndex + 3] == 'l' && s[characterIndex + 4] == '=') { linkStart = characterIndex; } else linkStart = s.LastIndexOf("[url=", characterIndex); if (linkStart == -1) return null; linkStart += 5; int linkEnd = s.IndexOf("]", linkStart); if (linkEnd == -1) return null; int urlEnd = s.IndexOf("[/url]", linkEnd); if (urlEnd == -1 || characterIndex <= urlEnd) return s.Substring(linkStart, linkEnd - linkStart); } return null; } /// <summary> /// Get the index of the character on the line directly above or below the current index. /// </summary> public int GetCharacterIndex (int currentIndex, KeyCode key) { if (isValid) { string text = processedText; if (string.IsNullOrEmpty(text)) return 0; int def = defaultFontSize; UpdateNGUIText(); NGUIText.PrintApproximateCharacterPositions(text, mTempVerts, mTempIndices); if (mTempVerts.Count > 0) { ApplyOffset(mTempVerts, 0); for (int i = 0, imax = mTempIndices.Count; i < imax; ++i) { if (mTempIndices[i] == currentIndex) { // Determine position on the line above or below this character Vector2 localPos = mTempVerts[i]; if (key == KeyCode.UpArrow) localPos.y += def + effectiveSpacingY; else if (key == KeyCode.DownArrow) localPos.y -= def + effectiveSpacingY; else if (key == KeyCode.Home) localPos.x -= 1000f; else if (key == KeyCode.End) localPos.x += 1000f; // Find the closest character to this position int retVal = NGUIText.GetApproximateCharacterIndex(mTempVerts, mTempIndices, localPos); if (retVal == currentIndex) break; mTempVerts.Clear(); mTempIndices.Clear(); return retVal; } } mTempVerts.Clear(); mTempIndices.Clear(); } NGUIText.bitmapFont = null; NGUIText.dynamicFont = null; // If the selection doesn't move, then we're at the top or bottom-most line if (key == KeyCode.UpArrow || key == KeyCode.Home) return 0; if (key == KeyCode.DownArrow || key == KeyCode.End) return text.Length; } return currentIndex; } /// <summary> /// Fill the specified geometry buffer with vertices that would highlight the current selection. /// </summary> public void PrintOverlay (int start, int end, UIGeometry caret, UIGeometry highlight, Color caretColor, Color highlightColor) { if (caret != null) caret.Clear(); if (highlight != null) highlight.Clear(); if (!isValid) return; string text = processedText; UpdateNGUIText(); int startingCaretVerts = caret.verts.Count; Vector2 center = new Vector2(0.5f, 0.5f); float alpha = finalAlpha; // If we have a highlight to work with, fill the buffer if (highlight != null && start != end) { int startingVertices = highlight.verts.Count; NGUIText.PrintCaretAndSelection(text, start, end, caret.verts, highlight.verts); if (highlight.verts.Count > startingVertices) { ApplyOffset(highlight.verts, startingVertices); Color c = new Color(highlightColor.r, highlightColor.g, highlightColor.b, highlightColor.a * alpha); for (int i = startingVertices, imax = highlight.verts.Count; i < imax; ++i) { highlight.uvs.Add(center); highlight.cols.Add(c); } } } else NGUIText.PrintCaretAndSelection(text, start, end, caret.verts, null); // Fill the caret UVs and colors ApplyOffset(caret.verts, startingCaretVerts); Color cc = new Color(caretColor.r, caretColor.g, caretColor.b, caretColor.a * alpha); for (int i = startingCaretVerts, imax = caret.verts.Count; i < imax; ++i) { caret.uvs.Add(center); caret.cols.Add(cc); } NGUIText.bitmapFont = null; NGUIText.dynamicFont = null; } /// <summary> /// Draw the label. /// </summary> public override void OnFill (List<Vector3> verts, List<Vector2> uvs, List<Color> cols) { if (!isValid) return; int offset = verts.Count; Color col = color; col.a = finalAlpha; if (mFont != null && mFont.premultipliedAlphaShader) col = NGUITools.ApplyPMA(col); string text = processedText; int start = verts.Count; UpdateNGUIText(); NGUIText.tint = col; NGUIText.Print(text, verts, uvs, cols); NGUIText.bitmapFont = null; NGUIText.dynamicFont = null; // Center the content within the label vertically Vector2 pos = ApplyOffset(verts, start); // Effects don't work with packed fonts if (mFont != null && mFont.packedFontShader) return; // Apply an effect if one was requested if (effectStyle != Effect.None) { int end = verts.Count; pos.x = mEffectDistance.x; pos.y = mEffectDistance.y; ApplyShadow(verts, uvs, cols, offset, end, pos.x, -pos.y); if ((effectStyle == Effect.Outline) || (effectStyle == Effect.Outline8)) { offset = end; end = verts.Count; ApplyShadow(verts, uvs, cols, offset, end, -pos.x, pos.y); offset = end; end = verts.Count; ApplyShadow(verts, uvs, cols, offset, end, pos.x, pos.y); offset = end; end = verts.Count; ApplyShadow(verts, uvs, cols, offset, end, -pos.x, -pos.y); if (effectStyle == Effect.Outline8) { offset = end; end = verts.Count; ApplyShadow(verts, uvs, cols, offset, end, -pos.x, 0); offset = end; end = verts.Count; ApplyShadow(verts, uvs, cols, offset, end, pos.x, 0); offset = end; end = verts.Count; ApplyShadow(verts, uvs, cols, offset, end, 0, pos.y); offset = end; end = verts.Count; ApplyShadow(verts, uvs, cols, offset, end, 0, -pos.y); } } } if (onPostFill != null) onPostFill(this, offset, verts, uvs, cols); } /// <summary> /// Align the vertices, making the label positioned correctly based on the pivot. /// Returns the offset that was applied. /// </summary> public Vector2 ApplyOffset (List<Vector3> verts, int start) { Vector2 po = pivotOffset; float fx = Mathf.Lerp(0f, -mWidth, po.x); float fy = Mathf.Lerp(mHeight, 0f, po.y) + Mathf.Lerp((mCalculatedSize.y - mHeight), 0f, po.y); fx = Mathf.Round(fx); fy = Mathf.Round(fy); Vector3 v; for (int i = start, imax = verts.Count; i < imax; ++i) { v = verts[i]; v.x += fx; v.y += fy; verts[i] = v; } return new Vector2(fx, fy); } /// <summary> /// Apply a shadow effect to the buffer. /// </summary> public void ApplyShadow (List<Vector3> verts, List<Vector2> uvs, List<Color> cols, int start, int end, float x, float y) { Color c = mEffectColor; c.a *= finalAlpha; if (bitmapFont != null && bitmapFont.premultipliedAlphaShader) c = NGUITools.ApplyPMA(c); Color col = c; for (int i = start; i < end; ++i) { verts.Add(verts[i]); uvs.Add(uvs[i]); cols.Add(cols[i]); var v = verts[i]; v.x += x; v.y += y; verts[i] = v; Color uc = cols[i]; if (uc.a == 1f) { cols[i] = col; } else { Color fc = c; fc.a = uc.a * c.a; cols[i] = fc; } } } /// <summary> /// Calculate the character index offset necessary in order to print the end of the specified text. /// </summary> public int CalculateOffsetToFit (string text) { UpdateNGUIText(); NGUIText.encoding = false; NGUIText.symbolStyle = NGUIText.SymbolStyle.None; int offset = NGUIText.CalculateOffsetToFit(text); NGUIText.bitmapFont = null; NGUIText.dynamicFont = null; return offset; } /// <summary> /// Convenience function, in case you wanted to associate progress bar, slider or scroll bar's /// OnValueChanged function in inspector with a label. /// </summary> public void SetCurrentProgress () { if (UIProgressBar.current != null) text = UIProgressBar.current.value.ToString("F"); } /// <summary> /// Convenience function, in case you wanted to associate progress bar, slider or scroll bar's /// OnValueChanged function in inspector with a label. /// </summary> public void SetCurrentPercent () { if (UIProgressBar.current != null) text = Mathf.RoundToInt(UIProgressBar.current.value * 100f) + "%"; } /// <summary> /// Convenience function, in case you wanted to automatically set some label's text /// by selecting a value in the UIPopupList. /// </summary> public void SetCurrentSelection () { if (UIPopupList.current != null) { text = UIPopupList.current.isLocalized ? Localization.Get(UIPopupList.current.value) : UIPopupList.current.value; } } /// <summary> /// Convenience function -- wrap the current text given the label's settings and unlimited height. /// </summary> public bool Wrap (string text, out string final) { return Wrap(text, out final, 1000000); } /// <summary> /// Convenience function -- wrap the current text given the label's settings and the given height. /// </summary> public bool Wrap (string text, out string final, int height) { UpdateNGUIText(); NGUIText.rectHeight = height; NGUIText.regionHeight = height; bool retVal = NGUIText.WrapText(text, out final); NGUIText.bitmapFont = null; NGUIText.dynamicFont = null; return retVal; } /// <summary> /// Update NGUIText.current with all the properties from this label. /// </summary> public void UpdateNGUIText () { Font ttf = trueTypeFont; bool isDynamic = (ttf != null); UpdateFontStyle(); NGUIText.fontSize = mFinalFontSize; NGUIText.fontStyle = mFontStyle; NGUIText.rectWidth = mWidth; NGUIText.rectHeight = mHeight; NGUIText.regionWidth = Mathf.RoundToInt(mWidth * (mDrawRegion.z - mDrawRegion.x)); NGUIText.regionHeight = Mathf.RoundToInt(mHeight * (mDrawRegion.w - mDrawRegion.y)); NGUIText.gradient = mApplyGradient && (mFont == null || !mFont.packedFontShader); NGUIText.gradientTop = mGradientTop; NGUIText.gradientBottom = mGradientBottom; NGUIText.encoding = mEncoding; NGUIText.premultiply = mPremultiply; NGUIText.symbolStyle = mSymbols; NGUIText.maxLines = mMaxLineCount; NGUIText.spacingX = effectiveSpacingX; NGUIText.spacingY = effectiveSpacingY; NGUIText.fontScale = isDynamic ? mScale : ((float)mFontSize / mFont.defaultSize) * mScale; if (mFont != null) { NGUIText.bitmapFont = mFont; for (; ; ) { UIFont fnt = NGUIText.bitmapFont.replacement; if (fnt == null) break; NGUIText.bitmapFont = fnt; } if (NGUIText.bitmapFont.isDynamic) { NGUIText.dynamicFont = NGUIText.bitmapFont.dynamicFont; NGUIText.bitmapFont = null; } else NGUIText.dynamicFont = null; } else { NGUIText.dynamicFont = ttf; NGUIText.bitmapFont = null; } if (isDynamic && keepCrisp) { UIRoot rt = root; if (rt != null) NGUIText.pixelDensity = (rt != null) ? rt.pixelSizeAdjustment : 1f; } else NGUIText.pixelDensity = 1f; if (mDensity != NGUIText.pixelDensity) { ProcessText(false, false); NGUIText.rectWidth = mWidth; NGUIText.rectHeight = mHeight; NGUIText.regionWidth = Mathf.RoundToInt(mWidth * (mDrawRegion.z - mDrawRegion.x)); NGUIText.regionHeight = Mathf.RoundToInt(mHeight * (mDrawRegion.w - mDrawRegion.y)); } if (alignment == Alignment.Automatic) { Pivot p = pivot; if (p == Pivot.Left || p == Pivot.TopLeft || p == Pivot.BottomLeft) { NGUIText.alignment = Alignment.Left; } else if (p == Pivot.Right || p == Pivot.TopRight || p == Pivot.BottomRight) { NGUIText.alignment = Alignment.Right; } else NGUIText.alignment = Alignment.Center; } else NGUIText.alignment = alignment; NGUIText.Update(); } void OnApplicationPause (bool paused) { if (!paused && mTrueTypeFont != null) Invalidate(false); } #region 预定义几种常用字体样式 public enum FontStyleEnum { None, Normal, Tab1, Tab2, Button1, Button2, Description, AttributeNumber, Quality1, Quality2, Quality3, Quality4, Quality5, Red, Green, LightBlue, Yellow, GradientYellow, Gray } [HideInInspector] [SerializeField] FontStyleEnum mFontStyleEnum = FontStyleEnum.None; static List<CommonFontStyle> fontStyleList = null; class CommonFontStyle { public int fontSize = 24; public FontStyle fontStyle = FontStyle.Normal; public bool applyGradient = false; //是否应用渐变 public Color gradientTop = Color.white; public Color gradientBottom = Color.yellow; public Color color = Color.white; public UILabel.Effect effectStyle = UILabel.Effect.None; public Color effectColor = Color.black; public string description = "描述信息"; } public static void LoadFontStyleConfig() { #if UNITY_EDITOR string fileName = Directory.GetCurrentDirectory() + @"\Assets\NGUI\fontstyle.txt"; if (!File.Exists(fileName)) { Debug.Log("Not found fontstyle.txt"); return; } if (null == fontStyleList) fontStyleList = new List<CommonFontStyle>(); fontStyleList.Clear(); fontStyleList.Add(null);//0号元素为 None string text = File.ReadAllText(fileName); JsonReader reader = new JsonReader(text); JsonData arr = JsonMapper.ToObject(reader); if (!arr.IsArray) return; double r, g, b, a; for (int i = 0; i < arr.Count; i++) { JsonData data = arr[i]; CommonFontStyle cfs = new CommonFontStyle(); cfs.fontSize = (int)data["fontSize"]; cfs.fontStyle = (FontStyle)Enum.Parse(typeof(FontStyle), (string)data["fontStyle"]); cfs.applyGradient = (bool)data["applyGradient"]; JsonParseColor(data, "gradientTop", out r, out g, out b, out a); cfs.gradientTop = new Color((float)r, (float)g, (float)b, (float)a); JsonParseColor(data, "gradientBottom", out r, out g, out b, out a); cfs.gradientBottom = new Color((float)r, (float)g, (float)b, (float)a); JsonParseColor(data, "color", out r, out g, out b, out a); cfs.color = new Color((float)r, (float)g, (float)b, (float)a); cfs.effectStyle = (UILabel.Effect)Enum.Parse(typeof(UILabel.Effect), (string)data["effectStyle"]); JsonParseColor(data, "effectColor", out r, out g, out b, out a); cfs.effectColor = new Color((float)r, (float)g, (float)b, (float)a); cfs.description = (string)data["description"]; fontStyleList.Add(cfs); } Debug.Log("Load fontstyle.txt completed!"); #endif } #if UNITY_EDITOR static void JsonParseColor(JsonData data, string key, out double r, out double g, out double b, out double a) { r = (double)data[key]["r"]; g = (double)data[key]["g"]; b = (double)data[key]["b"]; a = (double)data[key]["a"]; } #endif void SetLabelFontStyle(FontStyleEnum fontStyleEnum) { if (fontStyleEnum == FontStyleEnum.None) return; if (null == fontStyleList) LoadFontStyleConfig(); if (null == fontStyleList) return; int index = (int)fontStyleEnum; CommonFontStyle style = null; if (index >= fontStyleList.Count) return; style = fontStyleList[index]; if (null == style) return; this.fontStyle = style.fontStyle; this.fontSize = style.fontSize; this.applyGradient = style.applyGradient; this.gradientTop = style.gradientTop; this.gradientBottom = style.gradientBottom; this.color = style.color; this.effectStyle = style.effectStyle; this.effectColor = style.effectColor; this.MarkAsChanged(); } public void UpdateFontStyle() { SetLabelFontStyle(mFontStyleEnum); } public string GetFontStyleDescription() { if (mFontStyleEnum == FontStyleEnum.None) return string.Empty; int index = (int)mFontStyleEnum; if (null == fontStyleList || index >= fontStyleList.Count) return string.Empty; CommonFontStyle style = fontStyleList[index]; if (null == style) return string.Empty; return style.description; } #endregion }
二、修改UILabelInspector.cs
//------------------------------------------------- // NGUI: Next-Gen UI kit // Copyright © 2011-2017 Tasharen Entertainment Inc //------------------------------------------------- #if !UNITY_FLASH #define DYNAMIC_FONT #endif using UnityEngine; using UnityEditor; /// <summary> /// Inspector class used to edit UILabels. /// </summary> [CanEditMultipleObjects] [CustomEditor(typeof(UILabel), true)] public class UILabelInspector : UIWidgetInspector { public enum FontType { NGUI, Unity, } UILabel mLabel; FontType mFontType; protected override void OnEnable () { base.OnEnable(); SerializedProperty bit = serializedObject.FindProperty("mFont"); mFontType = (bit != null && bit.objectReferenceValue != null) ? FontType.NGUI : FontType.Unity; } void OnNGUIFont (Object obj) { serializedObject.Update(); SerializedProperty sp = serializedObject.FindProperty("mFont"); sp.objectReferenceValue = obj; sp = serializedObject.FindProperty("mTrueTypeFont"); sp.objectReferenceValue = null; serializedObject.ApplyModifiedProperties(); NGUISettings.ambigiousFont = obj; } void OnUnityFont (Object obj) { serializedObject.Update(); SerializedProperty sp = serializedObject.FindProperty("mTrueTypeFont"); sp.objectReferenceValue = obj; sp = serializedObject.FindProperty("mFont"); sp.objectReferenceValue = null; serializedObject.ApplyModifiedProperties(); NGUISettings.ambigiousFont = obj; } /// <summary> /// Draw the label's properties. /// </summary> protected override bool ShouldDrawProperties () { mLabel = mWidget as UILabel; GUILayout.BeginHorizontal(); #if DYNAMIC_FONT mFontType = (FontType)EditorGUILayout.EnumPopup(mFontType, "DropDown", GUILayout.Width(74f)); if (NGUIEditorTools.DrawPrefixButton("Font", GUILayout.Width(64f))) #else mFontType = FontType.NGUI; if (NGUIEditorTools.DrawPrefixButton("Font", GUILayout.Width(74f))) #endif { if (mFontType == FontType.NGUI) { ComponentSelector.Show<UIFont>(OnNGUIFont); } else { ComponentSelector.Show<Font>(OnUnityFont, new string[] { ".ttf", ".otf" }); } } bool isValid = false; SerializedProperty fnt = null; SerializedProperty ttf = null; if (mFontType == FontType.NGUI) { GUI.changed = false; fnt = NGUIEditorTools.DrawProperty("", serializedObject, "mFont", GUILayout.MinWidth(40f)); if (fnt.objectReferenceValue != null) { if (GUI.changed) serializedObject.FindProperty("mTrueTypeFont").objectReferenceValue = null; NGUISettings.ambigiousFont = fnt.objectReferenceValue; isValid = true; } } else { GUI.changed = false; ttf = NGUIEditorTools.DrawProperty("", serializedObject, "mTrueTypeFont", GUILayout.MinWidth(40f)); if (ttf.objectReferenceValue != null) { if (GUI.changed) serializedObject.FindProperty("mFont").objectReferenceValue = null; NGUISettings.ambigiousFont = ttf.objectReferenceValue; isValid = true; } } GUILayout.EndHorizontal(); //if (mFontType == FontType.Unity) //{ // EditorGUILayout.HelpBox("Dynamic fonts suffer from issues in Unity itself where your characters may disappear, get garbled, or just not show at times. Use this feature at your own risk.\n\n" + // "When you do run into such issues, please submit a Bug Report to Unity via Help -> Report a Bug (as this is will be a Unity bug, not an NGUI one).", MessageType.Warning); //} NGUIEditorTools.DrawProperty("Material", serializedObject, "mMat"); #region 新增常用字体样式 GUI.changed = false; Rect pRect = EditorGUILayout.GetControlRect(GUILayout.Height(16)); GUIContent fs_label = new GUIContent("Font Style"); SerializedProperty fs_sp = serializedObject.FindProperty("mFontStyleEnum"); UILabel.FontStyleEnum mFontStyleIndex = (UILabel.FontStyleEnum)EditorGUI.EnumPopup(pRect, fs_label, (UILabel.FontStyleEnum)fs_sp.enumValueIndex); if (GUI.changed) { fs_sp.enumValueIndex = (int)mFontStyleIndex; } if (mFontStyleIndex != UILabel.FontStyleEnum.None && string.Empty != mLabel.GetFontStyleDescription()) { EditorGUILayout.HelpBox(mLabel.GetFontStyleDescription(), MessageType.Info); } #endregion EditorGUI.BeginDisabledGroup(!isValid); { UIFont uiFont = (fnt != null) ? fnt.objectReferenceValue as UIFont : null; Font dynFont = (ttf != null) ? ttf.objectReferenceValue as Font : null; if (uiFont != null && uiFont.isDynamic) { dynFont = uiFont.dynamicFont; uiFont = null; } if (dynFont != null) { GUILayout.BeginHorizontal(); { EditorGUI.BeginDisabledGroup((ttf != null) ? ttf.hasMultipleDifferentValues : fnt.hasMultipleDifferentValues); SerializedProperty prop = NGUIEditorTools.DrawProperty("Font Size", serializedObject, "mFontSize", GUILayout.Width(142f)); NGUISettings.fontSize = prop.intValue; prop = NGUIEditorTools.DrawProperty("", serializedObject, "mFontStyle", GUILayout.MinWidth(40f)); NGUISettings.fontStyle = (FontStyle)prop.intValue; NGUIEditorTools.DrawPadding(); EditorGUI.EndDisabledGroup(); } GUILayout.EndHorizontal(); } else if (uiFont != null) { GUILayout.BeginHorizontal(); SerializedProperty prop = NGUIEditorTools.DrawProperty("Font Size", serializedObject, "mFontSize", GUILayout.Width(142f)); EditorGUI.BeginDisabledGroup(true); if (!serializedObject.isEditingMultipleObjects) { if (mLabel.overflowMethod == UILabel.Overflow.ShrinkContent) GUILayout.Label(" Actual: " + mLabel.finalFontSize + "/" + mLabel.defaultFontSize); else GUILayout.Label(" Default: " + mLabel.defaultFontSize); } EditorGUI.EndDisabledGroup(); NGUISettings.fontSize = prop.intValue; GUILayout.EndHorizontal(); } bool ww = GUI.skin.textField.wordWrap; GUI.skin.textField.wordWrap = true; SerializedProperty sp = serializedObject.FindProperty("mText"); if (sp.hasMultipleDifferentValues) { NGUIEditorTools.DrawProperty("", sp, GUILayout.Height(128f)); } else { GUIStyle style = new GUIStyle(EditorStyles.textField); style.wordWrap = true; float height = style.CalcHeight(new GUIContent(sp.stringValue), Screen.width - 100f); bool offset = true; if (height > 90f) { offset = false; height = style.CalcHeight(new GUIContent(sp.stringValue), Screen.width - 20f); } else { GUILayout.BeginHorizontal(); GUILayout.BeginVertical(GUILayout.Width(76f)); GUILayout.Space(3f); GUILayout.Label("Text"); GUILayout.EndVertical(); GUILayout.BeginVertical(); } Rect rect = EditorGUILayout.GetControlRect(GUILayout.Height(height)); GUI.changed = false; string text = EditorGUI.TextArea(rect, sp.stringValue, style); if (GUI.changed) sp.stringValue = text; if (offset) { GUILayout.EndVertical(); GUILayout.EndHorizontal(); } } GUI.skin.textField.wordWrap = ww; NGUIEditorTools.DrawPaddedProperty("Modifier", serializedObject, "mModifier"); SerializedProperty ov = NGUIEditorTools.DrawPaddedProperty("Overflow", serializedObject, "mOverflow"); NGUISettings.overflowStyle = (UILabel.Overflow)ov.intValue; if (NGUISettings.overflowStyle == UILabel.Overflow.ClampContent) NGUIEditorTools.DrawProperty("Use Ellipsis", serializedObject, "mOverflowEllipsis", GUILayout.Width(110f)); if (NGUISettings.overflowStyle == UILabel.Overflow.ResizeFreely) { GUILayout.BeginHorizontal(); SerializedProperty s = NGUIEditorTools.DrawPaddedProperty("Max Width", serializedObject, "mOverflowWidth"); if (s != null && s.intValue < 1) GUILayout.Label("unlimited"); GUILayout.EndHorizontal(); } NGUIEditorTools.DrawPaddedProperty("Alignment", serializedObject, "mAlignment"); if (dynFont != null) NGUIEditorTools.DrawPaddedProperty("Keep crisp", serializedObject, "keepCrispWhenShrunk"); EditorGUI.BeginDisabledGroup(mLabel.bitmapFont != null && mLabel.bitmapFont.packedFontShader); GUILayout.BeginHorizontal(); SerializedProperty gr = NGUIEditorTools.DrawProperty("Gradient", serializedObject, "mApplyGradient", GUILayout.Width(95f)); EditorGUI.BeginDisabledGroup(!gr.hasMultipleDifferentValues && !gr.boolValue); { NGUIEditorTools.SetLabelWidth(30f); NGUIEditorTools.DrawProperty("Top", serializedObject, "mGradientTop", GUILayout.MinWidth(40f)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); NGUIEditorTools.SetLabelWidth(50f); GUILayout.Space(79f); NGUIEditorTools.DrawProperty("Bottom", serializedObject, "mGradientBottom", GUILayout.MinWidth(40f)); NGUIEditorTools.SetLabelWidth(80f); } EditorGUI.EndDisabledGroup(); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Effect", GUILayout.Width(76f)); sp = NGUIEditorTools.DrawProperty("", serializedObject, "mEffectStyle", GUILayout.MinWidth(16f)); EditorGUI.BeginDisabledGroup(!sp.hasMultipleDifferentValues && !sp.boolValue); { NGUIEditorTools.DrawProperty("", serializedObject, "mEffectColor", GUILayout.MinWidth(10f)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); { GUILayout.Label(" ", GUILayout.Width(56f)); NGUIEditorTools.SetLabelWidth(20f); NGUIEditorTools.DrawProperty("X", serializedObject, "mEffectDistance.x", GUILayout.MinWidth(40f)); NGUIEditorTools.DrawProperty("Y", serializedObject, "mEffectDistance.y", GUILayout.MinWidth(40f)); NGUIEditorTools.DrawPadding(); NGUIEditorTools.SetLabelWidth(80f); } } EditorGUI.EndDisabledGroup(); GUILayout.EndHorizontal(); EditorGUI.EndDisabledGroup(); sp = NGUIEditorTools.DrawProperty("Float spacing", serializedObject, "mUseFloatSpacing", GUILayout.Width(100f)); if (!sp.boolValue) { GUILayout.BeginHorizontal(); GUILayout.Label("Spacing", GUILayout.Width(56f)); NGUIEditorTools.SetLabelWidth(20f); NGUIEditorTools.DrawProperty("X", serializedObject, "mSpacingX", GUILayout.MinWidth(40f)); NGUIEditorTools.DrawProperty("Y", serializedObject, "mSpacingY", GUILayout.MinWidth(40f)); NGUIEditorTools.DrawPadding(); NGUIEditorTools.SetLabelWidth(80f); GUILayout.EndHorizontal(); } else { GUILayout.BeginHorizontal(); GUILayout.Label("Spacing", GUILayout.Width(56f)); NGUIEditorTools.SetLabelWidth(20f); NGUIEditorTools.DrawProperty("X", serializedObject, "mFloatSpacingX", GUILayout.MinWidth(40f)); NGUIEditorTools.DrawProperty("Y", serializedObject, "mFloatSpacingY", GUILayout.MinWidth(40f)); NGUIEditorTools.DrawPadding(); NGUIEditorTools.SetLabelWidth(80f); GUILayout.EndHorizontal(); } NGUIEditorTools.DrawProperty("Max Lines", serializedObject, "mMaxLineCount", GUILayout.Width(110f)); GUILayout.BeginHorizontal(); sp = NGUIEditorTools.DrawProperty("BBCode", serializedObject, "mEncoding", GUILayout.Width(100f)); EditorGUI.BeginDisabledGroup(!sp.boolValue || mLabel.bitmapFont == null || !mLabel.bitmapFont.hasSymbols); NGUIEditorTools.SetLabelWidth(60f); NGUIEditorTools.DrawPaddedProperty("Symbols", serializedObject, "mSymbols"); NGUIEditorTools.SetLabelWidth(80f); EditorGUI.EndDisabledGroup(); GUILayout.EndHorizontal(); } EditorGUI.EndDisabledGroup(); return isValid; } }
三、添加导出字体设置信息菜单
using UnityEngine; using UnityEditor; using System.Collections; using System.Collections.Generic; using System; using System.IO; static public class UIToolsEditor { #region UILabel 导出字体样式设置 [MenuItem("NGUI/Label Setting/Output Setting")] static void LabelOutputSetting() { GameObject[] gameObjects = Selection.gameObjects; if (null == gameObjects) return; StringBuilder sb = new StringBuilder(); for (int i = 0; i < gameObjects.Length; i++) { GameObject go = gameObjects[i]; UILabel label = go.GetComponent<UILabel>(); if (null == label) continue; CommonFontStyleJson cfs = new CommonFontStyleJson(); cfs.fontSize = label.fontSize; cfs.applyGradient = label.applyGradient; cfs.gradientTop = new CommonFontStyleColor(label.gradientTop.r, label.gradientTop.g, label.gradientTop.b, label.gradientTop.a); cfs.gradientBottom = new CommonFontStyleColor(label.gradientBottom.r, label.gradientBottom.g, label.gradientBottom.b, label.gradientBottom.a); cfs.color = new CommonFontStyleColor(label.color.r, label.color.g, label.color.b, label.color.a); cfs.effectStyle = label.effectStyle.ToString(); cfs.effectColor = new CommonFontStyleColor(label.effectColor.r, label.effectColor.g, label.effectColor.b, label.effectColor.a); Debug.Log(LitJson.JsonMapper.ToJson(cfs, true)); sb.AppendLine(LitJson.JsonMapper.ToJson(cfs, true)); } if (sb.Length > 0) { string font_str = sb.ToString(); byte[] font_bytes = Encoding.UTF8.GetBytes(font_str.ToCharArray()); string font_file = Application.dataPath + "/NGUI/fontstyle_tmp.txt"; FileStream fs = File.OpenWrite(font_file); fs.Write(font_bytes, 0, font_bytes.Length); fs.Flush(); AssetDatabase.Refresh(); Debug.Log("Output: "+font_file); } } [MenuItem("NGUI/Label Setting/Reload fontstyle.txt")] static void ReloadFontStyleConfig() { UILabel.LoadFontStyleConfig(); } public class CommonFontStyleJson { public int fontSize; public bool applyGradient; public CommonFontStyleColor gradientTop; public CommonFontStyleColor gradientBottom; public CommonFontStyleColor color; public string effectStyle; public CommonFontStyleColor effectColor; public string description = "描述信息"; } public class CommonFontStyleColor { //LitJson不支持float public double r; public double g; public double b; public double a; public CommonFontStyleColor(float r, float g, float b, float a) { this.r = r; this.g = g; this.b = b; this.a = a; } } #endregion }
效果截图
标签: NGUI
日历
最新文章
随机文章
热门文章
分类
存档
- 2024年11月(3)
- 2024年10月(5)
- 2024年9月(3)
- 2024年8月(3)
- 2024年7月(11)
- 2024年6月(3)
- 2024年5月(9)
- 2024年4月(10)
- 2024年3月(11)
- 2024年2月(24)
- 2024年1月(12)
- 2023年12月(3)
- 2023年11月(9)
- 2023年10月(7)
- 2023年9月(2)
- 2023年8月(7)
- 2023年7月(9)
- 2023年6月(6)
- 2023年5月(7)
- 2023年4月(11)
- 2023年3月(6)
- 2023年2月(11)
- 2023年1月(8)
- 2022年12月(2)
- 2022年11月(4)
- 2022年10月(10)
- 2022年9月(2)
- 2022年8月(13)
- 2022年7月(7)
- 2022年6月(11)
- 2022年5月(18)
- 2022年4月(29)
- 2022年3月(5)
- 2022年2月(6)
- 2022年1月(8)
- 2021年12月(5)
- 2021年11月(3)
- 2021年10月(4)
- 2021年9月(9)
- 2021年8月(14)
- 2021年7月(8)
- 2021年6月(5)
- 2021年5月(2)
- 2021年4月(3)
- 2021年3月(7)
- 2021年2月(2)
- 2021年1月(8)
- 2020年12月(7)
- 2020年11月(2)
- 2020年10月(6)
- 2020年9月(9)
- 2020年8月(10)
- 2020年7月(9)
- 2020年6月(18)
- 2020年5月(4)
- 2020年4月(25)
- 2020年3月(38)
- 2020年1月(21)
- 2019年12月(13)
- 2019年11月(29)
- 2019年10月(44)
- 2019年9月(17)
- 2019年8月(18)
- 2019年7月(25)
- 2019年6月(25)
- 2019年5月(17)
- 2019年4月(10)
- 2019年3月(36)
- 2019年2月(35)
- 2019年1月(28)
- 2018年12月(30)
- 2018年11月(22)
- 2018年10月(4)
- 2018年9月(7)
- 2018年8月(13)
- 2018年7月(13)
- 2018年6月(6)
- 2018年5月(5)
- 2018年4月(13)
- 2018年3月(5)
- 2018年2月(3)
- 2018年1月(8)
- 2017年12月(35)
- 2017年11月(17)
- 2017年10月(16)
- 2017年9月(17)
- 2017年8月(20)
- 2017年7月(34)
- 2017年6月(17)
- 2017年5月(15)
- 2017年4月(32)
- 2017年3月(8)
- 2017年2月(2)
- 2017年1月(5)
- 2016年12月(14)
- 2016年11月(26)
- 2016年10月(12)
- 2016年9月(25)
- 2016年8月(32)
- 2016年7月(14)
- 2016年6月(21)
- 2016年5月(17)
- 2016年4月(13)
- 2016年3月(8)
- 2016年2月(8)
- 2016年1月(18)
- 2015年12月(13)
- 2015年11月(15)
- 2015年10月(12)
- 2015年9月(18)
- 2015年8月(21)
- 2015年7月(35)
- 2015年6月(13)
- 2015年5月(9)
- 2015年4月(4)
- 2015年3月(5)
- 2015年2月(4)
- 2015年1月(13)
- 2014年12月(7)
- 2014年11月(5)
- 2014年10月(4)
- 2014年9月(8)
- 2014年8月(16)
- 2014年7月(26)
- 2014年6月(22)
- 2014年5月(28)
- 2014年4月(15)
友情链接
- Unity官网
- Unity圣典
- Unity在线手册
- Unity中文手册(圣典)
- Unity官方中文论坛
- Unity游戏蛮牛用户文档
- Unity下载存档
- Unity引擎源码下载
- Unity服务
- Unity Ads
- wiki.unity3d
- Visual Studio Code官网
- SenseAR开发文档
- MSDN
- C# 参考
- C# 编程指南
- .NET Framework类库
- .NET 文档
- .NET 开发
- WPF官方文档
- uLua
- xLua
- SharpZipLib
- Protobuf-net
- Protobuf.js
- OpenSSL
- OPEN CASCADE
- JSON
- MessagePack
- C在线工具
- 游戏蛮牛
- GreenVPN
- 聚合数据
- 热云
- 融云
- 腾讯云
- 腾讯开放平台
- 腾讯游戏服务
- 腾讯游戏开发者平台
- 腾讯课堂
- 微信开放平台
- 腾讯实时音视频
- 腾讯即时通信IM
- 微信公众平台技术文档
- 白鹭引擎官网
- 白鹭引擎开放平台
- 白鹭引擎开发文档
- FairyGUI编辑器
- PureMVC-TypeScript
- 讯飞开放平台
- 亲加通讯云
- Cygwin
- Mono开发者联盟
- Scut游戏服务器引擎
- KBEngine游戏服务器引擎
- Photon游戏服务器引擎
- 码云
- SharpSvn
- 腾讯bugly
- 4399原创平台
- 开源中国
- Firebase
- Firebase-Admob-Unity
- google-services-unity
- Firebase SDK for Unity
- Google-Firebase-SDK
- AppsFlyer SDK
- android-repository
- CQASO
- Facebook开发者平台
- gradle下载
- GradleBuildTool下载
- Android Developers
- Google中国开发者
- AndroidDevTools
- Android社区
- Android开发工具
- Google Play Games Services
- Google商店
- Google APIs for Android
- 金钱豹VPN
- TouchSense SDK
- MakeHuman
- Online RSA Key Converter
- Windows UWP应用
- Visual Studio For Unity
- Open CASCADE Technology
- 慕课网
- 阿里云服务器ECS
- 在线免费文字转语音系统
- AI Studio
- 网云穿
- 百度网盘开放平台
- 迅捷画图
- 菜鸟工具
- [CSDN] 程序员研修院
- 华为人脸识别
- 百度AR导航导览SDK
- 海康威视官网
- 海康开放平台
- 海康SDK下载
- git download
交流QQ群
-
Flash游戏设计: 86184192
Unity游戏设计: 171855449
游戏设计订阅号