void makeImage(GameObject img, LRenderElement elem)
    {
        Image comImage = img.GetComponent <Image>();

        comImage.color = Color.white;
        if (comImage != null)
        {
            Sprite sp = AssetBundleManager.godLoader.Load(GameResType.Emote, PathUtil.GetFileNameWithoutExtension(elem.path), typeof(Sprite)) as Sprite;
            comImage.sprite = sp;
        }
    }
    void makeFramAnim(GameObject anim, LRenderElement elem)
    {
        LMovieClip comFram = anim.GetComponent <LMovieClip>();

        if (comFram != null)
        {
            comFram.path        = elem.path;
            comFram.fps         = elem.fs;
            comFram.frameLength = elem.frameCount;
            comFram.loadTexture();
            comFram.play();
        }
    }
    void makeLabel(GameObject lab, LRenderElement elem)
    {
        Text comText = lab.GetComponent <Text>();

        if (comText != null)
        {
            comText.text      = elem.strChar;
            comText.font      = elem.font;
            comText.fontSize  = elem.fontSize;
            comText.fontStyle = FontStyle.Normal;
            comText.color     = elem.color;
        }

        Outline outline = lab.GetComponent <Outline>();

        if (elem.isOutLine)
        {
            if (outline == null)
            {
                outline = lab.AddComponent <Outline>();
            }
        }
        else
        {
            if (outline)
            {
                Destroy(outline);
            }
        }

        if (elem.isUnderLine)
        {
            GameObject underLine = getCacheImage(false);
            Image      underImg  = underLine.GetComponent <Image>();
            underImg.sprite = null;
            underImg.color  = elem.color;
            underImg.GetComponent <RectTransform>().sizeDelta = new Vector2(comText.preferredWidth, 2);
            underLine.transform.SetParent(transform);
            underLine.transform.localPosition = Vector3.zero;
            RectTransform rect = underLine.transform as RectTransform;
            rect.anchoredPosition = new Vector2(elem.pos.x, elem.pos.y);
            rect.localScale       = new Vector3(1, 1, 1);
            //underLine.transform.localPosition = new Vector2(elem.pos.x, elem.pos.y);
        }
    }
    protected void formarRenderers()
    {
        int  oneLine          = 0;
        int  lines            = 1;
        bool isReplaceInSpace = false;
        int  len = _elemRenderArr.Count;

        //这里开始根据刚才已经拆解过的单个元素的长宽,以及每行的最大宽度maxLineWidth
        //从而确定每个元素在每一行的大致相对位置
        for (int i = 0; i < len; i++)
        {
            isReplaceInSpace = false;
            LRenderElement elem = _elemRenderArr[i];
            if (elem.isNewLine) // new line
            {
                oneLine = 0;
                lines++;
                elem.width  = 10;
                elem.height = 27;
                elem.pos    = new Vector2(oneLine, -lines * 27);
            }
            else //other elements
            {
                if (oneLine + elem.width > maxLineWidth)
                {
                    if (elem.type == RichType.TEXT)
                    {
                        //if (isChinese(elem.strChar) || elem.strChar == " ")
                        //{
                        oneLine = 0;
                        lines++;

                        elem.pos = new Vector2(oneLine, -lines * 27);
                        oneLine  = elem.width;
                        //}
                        //else // en
                        //{
                        //    int spaceIdx = 0;
                        //    int idx = i;
                        //    while (idx > 0)
                        //    {
                        //        idx--;
                        //        if (_elemRenderArr[idx].strChar == " " &&
                        //            _elemRenderArr[idx].pos.y == _elemRenderArr[i-1].pos.y ) // just for the same line
                        //        {
                        //            spaceIdx = idx;
                        //            break;
                        //        }
                        //    }
                        //    // can't find space , force new line
                        //    if (spaceIdx == 0)
                        //    {
                        //        oneLine = 0;
                        //        lines++;
                        //        elem.pos = new Vector2(oneLine, -lines * 27);
                        //        oneLine = elem.width;
                        //    }
                        //    else
                        //    {
                        //        oneLine = 0;
                        //        lines++;
                        //        isReplaceInSpace = true; //reset cuting words position

                        //        for (int _i = spaceIdx +1; _i <= i; ++_i)
                        //        {
                        //            LRenderElement _elem = _elemRenderArr[_i];
                        //            _elem.pos = new Vector2(oneLine, -lines * 27);
                        //            oneLine += _elem.width;

                        //            _elemRenderArr[_i] = _elem;
                        //        }
                        //    }
                        //}
                    }
                    else if (elem.type == RichType.ANIM || elem.type == RichType.IMAGE)
                    {
                        lines++;
                        elem.pos = new Vector2(0, -lines * 27);
                        oneLine  = elem.width;
                    }
                }
                else
                {
                    elem.pos = new Vector2(oneLine, -lines * 27);
                    oneLine += elem.width;
                }
            }
            if (isReplaceInSpace == false)
            {
                _elemRenderArr[i] = elem;
            }
        }
        //sort all lines
        //根据每个元素的大致位置,确定最终的行数以及每一行所包含的所有元素
        Dictionary <int, List <LRenderElement> > rendElemLineMap = new Dictionary <int, List <LRenderElement> >();
        List <int> lineKeyList = new List <int>();

        len = _elemRenderArr.Count;
        for (int i = 0; i < len; i++)
        {
            LRenderElement        elem = _elemRenderArr[i];
            List <LRenderElement> lineList;

            if (!rendElemLineMap.ContainsKey((int)elem.pos.y))
            {
                lineList = new List <LRenderElement>();
                rendElemLineMap[(int)elem.pos.y] = lineList;
            }
            rendElemLineMap[(int)elem.pos.y].Add(elem);
        }
        // all lines in arr
        List <List <LRenderElement> > rendLineArrs = new List <List <LRenderElement> >();

        foreach (var item in rendElemLineMap)
        {
            lineKeyList.Add(-1 * item.Key);
        }
        lineKeyList.Sort();
        len = lineKeyList.Count;

        //这里开始将单个的元素再组装成一个渲染单元(String,Image,Anim等)
        for (int i = 0; i < len; i++)
        {
            int            posY                = -1 * lineKeyList[i];
            string         lineString          = "";
            LRenderElement _lastEleme          = rendElemLineMap[posY][0];
            LRenderElement _lastDiffStartEleme = rendElemLineMap[posY][0];
            if (rendElemLineMap[posY].Count > 0)
            {
                List <LRenderElement> lineElemArr = new List <LRenderElement>();

                foreach (LRenderElement elem in rendElemLineMap[posY])
                {
                    if (_lastEleme.type == RichType.TEXT && elem.type == RichType.TEXT)
                    {
                        if (_lastEleme.color == elem.color && _lastEleme.data == elem.data)
                        {
                            // the same color can mergin one string
                            lineString += elem.strChar;
                        }
                        else // diff color
                        {
                            if (_lastDiffStartEleme.type == RichType.TEXT)
                            {
                                LRenderElement _newElem = _lastDiffStartEleme.Clone();
                                _newElem.strChar = lineString;
                                lineElemArr.Add(_newElem);

                                _lastDiffStartEleme = elem;
                                lineString          = elem.strChar;
                            }
                        }
                    }
                    else if (elem.type == RichType.IMAGE || elem.type == RichType.ANIM || elem.type == RichType.NEWLINE)
                    {
                        //interrupt
                        if (_lastDiffStartEleme.type == RichType.TEXT)
                        {
                            LRenderElement _newEleme = _lastDiffStartEleme.Clone();
                            _newEleme.strChar = lineString;
                            lineString        = "";
                            lineElemArr.Add(_newEleme);
                        }
                        lineElemArr.Add(elem);
                    }
                    else if (_lastEleme.type != RichType.TEXT)
                    {
                        //interrupt
                        _lastDiffStartEleme = elem;
                        if (elem.type == RichType.TEXT)
                        {
                            lineString = elem.strChar;
                        }
                    }
                    _lastEleme = elem;
                }
                // the last elementText
                if (_lastDiffStartEleme.type == RichType.TEXT)
                {
                    LRenderElement _newElem = _lastDiffStartEleme.Clone();
                    _newElem.strChar = lineString;
                    lineElemArr.Add(_newElem);
                }
                rendLineArrs.Add(lineElemArr);
            }
        }

        // offset position
        //确定每个元素的最终y方向位置,并统计出所有行的总高度
        int _offsetLineY = 0;

        realLineHeight = 0;
        len            = rendLineArrs.Count;
        for (int i = 0; i < len; i++)
        {
            List <LRenderElement> _lines = rendLineArrs[i];
            int _lineHeight = 0;
            foreach (LRenderElement elem in _lines)
            {
                _lineHeight = Mathf.Max(_lineHeight, elem.height);
            }
            _lineHeight    += verticalSpace; //加入行间距
            realLineHeight += _lineHeight;
            _offsetLineY   += (_lineHeight - 27);

            int _len = _lines.Count;
            for (int j = 0; j < _len; j++)
            {
                LRenderElement elem = _lines[j];
                elem.pos       = new Vector2(elem.pos.x, elem.pos.y - _offsetLineY);
                realLineHeight = Mathf.Max(realLineHeight, (int)Mathf.Abs(elem.pos.y));
                _lines[j]      = elem;
            }
            rendLineArrs[i] = _lines;
        }

        // place all position
        //将每一个的各个组装好的元素转化为实际的gameObject,置为RichText对象的子对象,并统计出最终的宽度
        realLineWidth = 0;
        GameObject obj = null;

        foreach (List <LRenderElement> _lines in rendLineArrs)
        {
            int _lineWidth = 0;
            foreach (LRenderElement elem in _lines)
            {
                if (!elem.isNewLine)
                {
                    string strComponent = "Text";
                    if (elem.type == RichType.TEXT)
                    {
                        obj = getCacheLabel();
                        makeLabel(obj, elem);
                        _lineWidth  += (int)obj.GetComponent <Text>().preferredWidth;
                        strComponent = "Text";
                    }
                    else if (elem.type == RichType.IMAGE)
                    {
                        obj = getCacheImage(true);
                        makeImage(obj, elem);
                        _lineWidth  += (int)obj.GetComponent <Image>().preferredWidth;
                        strComponent = "Image";
                    }
                    else if (elem.type == RichType.ANIM)
                    {
                        obj = getCacheFramAnim();
                        makeFramAnim(obj, elem);
                        _lineWidth  += elem.width;
                        strComponent = "Animation";
                    }
                    obj.GetComponent <Graphic>().raycastTarget = RaycastTarget;;
                    obj.transform.SetParent(transform);
                    RectTransform rect = obj.transform as RectTransform;
                    rect.anchoredPosition3D = new Vector3(elem.pos.x, elem.pos.y /*+ realLineHeight*/, 0);
                    rect.localScale         = new Vector3(1, 1, 1);
                    _objectDataMap[obj]     = elem.data;
                }
            }
            realLineWidth = Mathf.Max(_lineWidth, realLineWidth);
        }

        //调整RichText对象的宽高
        RectTransform rtran = this.GetComponent <RectTransform>();

        //align
        if (alignType == RichAlignType.DESIGN_CENTER)
        {
            rtran.sizeDelta = new Vector2(realLineWidth, realLineHeight);
        }
        else if (alignType == RichAlignType.LEFT_TOP)
        {
            rtran.sizeDelta = new Vector2(realLineWidth, realLineHeight);
        }
    }
    //public LRichText(InputType inputType):this()
    //{
    //    this.inputType = inputType;
    //}

    //===================================================================
    //解析内部结构并生成相关GameObject的方法
    //===================================================================
    //将_richElements中的单个元素拆解为每个字符一个元素,这个时候是一字排开的状态
    //_elemRenderArr中存放的所有元素的list
    void reloadData()
    {
        this.removeAllElements();

        RectTransform rtran = this.GetComponent <RectTransform>();

        //align
        if (alignType == RichAlignType.DESIGN_CENTER)
        {
            rtran.GetComponent <RectTransform>().pivot = new Vector2(0.5f, 0.5f);
        }
        else if (alignType == RichAlignType.LEFT_TOP)
        {
            rtran.GetComponent <RectTransform>().pivot = new Vector2(0f, 1f);
        }

        foreach (LRichElement elem in _richElements)
        {
            if (elem.type == RichType.TEXT)
            {
                LRichElementText elemText = elem as LRichElementText;
                char[]           _charArr = elemText.txt.ToCharArray();
                TextGenerator    gen      = new TextGenerator();

                foreach (char strChar in _charArr)
                {
                    LRenderElement rendElem = new LRenderElement();
                    rendElem.type        = RichType.TEXT;
                    rendElem.strChar     = strChar.ToString();
                    rendElem.isOutLine   = elemText.isOutLine;
                    rendElem.isUnderLine = elemText.isUnderLine;
                    rendElem.font        = this.font;
                    rendElem.fontSize    = elemText.fontSize;
                    rendElem.data        = elemText.data;
                    rendElem.color       = elemText.color;

                    TextGenerationSettings setting = new TextGenerationSettings();
                    setting.font               = this.font;
                    setting.fontSize           = elemText.fontSize;
                    setting.lineSpacing        = 1;
                    setting.scaleFactor        = 1;
                    setting.verticalOverflow   = VerticalWrapMode.Overflow;
                    setting.horizontalOverflow = HorizontalWrapMode.Overflow;

                    rendElem.width  = (int)gen.GetPreferredWidth(rendElem.strChar, setting);
                    rendElem.height = (int)gen.GetPreferredHeight(rendElem.strChar, setting);
                    _elemRenderArr.Add(rendElem);
                }
            }
            else if (elem.type == RichType.IMAGE)
            {
                LRichElementImage elemImg  = elem as LRichElementImage;
                LRenderElement    rendElem = new LRenderElement();
                rendElem.type = RichType.IMAGE;
                rendElem.path = elemImg.path;
                rendElem.data = elemImg.data;
                //从配置直接传进来,不用再读取图片大小了
                //Sprite sp = Resources.LoadAssetAtPath(AppConst.RawResPath + rendElem.path, typeof(Sprite)) as Sprite;
                rendElem.width  = elemImg.width;
                rendElem.height = elemImg.height;
                _elemRenderArr.Add(rendElem);
            }
            else if (elem.type == RichType.ANIM)
            {
                LRichElementAnim elemAnim = elem as LRichElementAnim;
                LRenderElement   rendElem = new LRenderElement();
                rendElem.type       = RichType.ANIM;
                rendElem.path       = elemAnim.path;
                rendElem.data       = elemAnim.data;
                rendElem.frameCount = elemAnim.frameCount;
                rendElem.fs         = elemAnim.fs;
                //Sprite sp = Resources.LoadAssetAtPath(AppConst.RawResPath + rendElem.path + "/1", typeof(Sprite)) as Sprite;
                rendElem.width  = elemAnim.width;
                rendElem.height = elemAnim.height;
                _elemRenderArr.Add(rendElem);
            }
            else if (elem.type == RichType.NEWLINE)
            {
                LRenderElement rendElem = new LRenderElement();
                rendElem.isNewLine = true;
                _elemRenderArr.Add(rendElem);
            }
        }

        _richElements.Clear();

        formarRenderers();
    }