コード例 #1
0
    public void RecreateQuadBatch()
    {
        if (font == null)
        {
            return;
        }

        //
        // first, cut into lines
        //

        // the line list is a list of pair <first char index, line text>
        lineList.Clear();
        {
            int lineStartIndex = 0;
            int lineBreakIndex = 0;
            int length         = text.Length;
            while (lineBreakIndex < length)
            {
                char c          = text[lineBreakIndex];
                bool antiSlashN = (c == '\n');
                bool antiSlashR = (c == '\r');
                if (antiSlashN || antiSlashR)
                {
                    lineList.Add(new LineDescriptor(lineStartIndex, (lineBreakIndex - lineStartIndex), false));

                    if (antiSlashR &&                                                           // if \r is found
                        (lineBreakIndex < length - 1) &&
                        (text[lineBreakIndex + 1] == '\n'))                                     // skip possible \n following it
                    {
                        lineBreakIndex++;
                    }

                    lineStartIndex = lineBreakIndex + 1;                     // start index of next line
                }
                lineBreakIndex++;
            }
            lineList.Add(new LineDescriptor(lineStartIndex, (text.Length - lineStartIndex), false));

//          int startIndex = 0;
//          int lineBreakIndex = -1;
//          while ( ( lineBreakIndex = text.IndexOf ( '\n', startIndex ) ) != -1 )
//          {
//              lineList.Add ( new LineDescriptor ( startIndex, lineBreakIndex - startIndex, false ) );
//              startIndex = lineBreakIndex + 1; // start index of next line
//          }
//          lineList.Add ( new LineDescriptor ( startIndex, text.Length - startIndex, false ) );
        }

#if UNITY_EDITOR
        errorMessage = null;
#endif

        //
        // new create lines geometry
        //

        quadBatch.setSize(text.Length);

        int     lineIndex      = 0;
        Vector3 linePosition   = new Vector3(position.x, position.y, position.z);
        int     quadStartIndex = 0;
        while (lineIndex < lineList.Count)
        {
            // TODO : optim : "lineList.get( lineIndex )" as local ?
            int  startIndex        = lineList[lineIndex].charStartIndexInText;
            int  length            = lineList[lineIndex].charCount;
            bool issuedFromLineCut = lineList[lineIndex].issuedFromLineCut;

            CreateTextGeometryResult result = createTextGeometry(linePosition, text, startIndex, length, quadStartIndex, issuedFromLineCut, scale, lineMaxWidth, preserveWords);

            if ((result.processedCharCount > 0) && (result.processedCharCount != length))                   // line not fully processed ? (see line break near end of
            // createTextGeometry method)
            {
                // insert remaining of the line
                lineList.Insert(lineIndex + 1, new LineDescriptor(startIndex + result.processedCharCount, length - result.processedCharCount, true));
            }

            // updates line description
            lineList[lineIndex] = new LineDescriptor(startIndex + result.spaceRemovedAtBeginning, result.processedCharCount - result.spaceRemovedAtBeginning, quadStartIndex, result.renderedCharCount, issuedFromLineCut);

            quadStartIndex += result.renderedCharCount;             // moves into the quad buffer

            if (fontData != null)
            {
                if (letterSpacingMode == LetterSpacingMode.Add)
                {
                    linePosition.y -= ((fontData.LineHeight + letterSpacing.y) * scale);
                }
                else
                {
                    linePosition.y -= (letterSpacing.y * scale);
                }
            }
            // TODO : might be an option instead of lineHeight : result.boundingRectMax.Y

            // result.boundingRectMin.Y;
            lineIndex++;
        }

#if UNITY_EDITOR
        if (errorMessage != null)
        {
            Debug.LogError("Invalid char found in text to render :\n" + errorMessage);
        }
#endif

        quadBatch.setSize(quadStartIndex);

        //
        // align each line's geometry
        //

        bounds = new Rect(0, 0, -1, -1);

        if (lineList.Count > 1)
        {
            float lineWidth = lineMaxWidth;

            if (
                (lineMaxWidth == float.MaxValue) ||
                (alignment == TextAlignment.Center)                     // we also want real width when centering
                )
            {
                bounds    = quadBatch.getBounds();
                lineWidth = bounds.width;
            }

            switch (alignment)
            {
            case TextAlignment.Left:
                // default alignment
                break;

            case TextAlignment.Center:
                for (int i = 0; i < lineList.Count; i++)
                {
                    LineDescriptor lineDesc     = lineList[i];
                    Rect           boundingRect = quadBatch.getBounds(lineDesc.quadStartIndexInBatch, lineDesc.quadCount);
                    quadBatch.translate(lineDesc.quadStartIndexInBatch, lineDesc.quadCount, new Vector3((lineWidth - boundingRect.width) / 2, 0, 0));
                }
                break;

            case TextAlignment.Right:
                for (int i = 0; i < lineList.Count; i++)
                {
                    LineDescriptor lineDesc     = lineList[i];
                    Rect           boundingRect = quadBatch.getBounds(lineDesc.quadStartIndexInBatch, lineDesc.quadCount);
                    quadBatch.translate(lineDesc.quadStartIndexInBatch, lineDesc.quadCount, new Vector3(lineWidth - boundingRect.width, 0, 0));
                }
                break;

            case TextAlignment.Justify:
                for (int i = 0; i < lineList.Count; i++)
                {
                    LineDescriptor lineDesc = lineList[i];

                    // line is cut if next line is issued from the cut
                    bool lineWasCut = (i < lineList.Count - 1) && (lineList[i + 1].issuedFromLineCut);

                    // TODO : add right/centered aligned justify as Photoshop do ?
                    if (lineWasCut)                               // only align line that are cut, others are already left aligned
                    {
                        // get space count in that line
                        List <int> charCountsToProcess = new List <int> ();
                        int        noSpaceCharCount    = 0;
                        for (int j = 0; j < lineDesc.charCount; j++)
                        {
                            char charToRender = text[lineDesc.charStartIndexInText + j];
                            if (charToRender == 0xA0)
                            {
                                charToRender = (char)0x20;                                         // convert unbreakable space into space
                            }
                            if (charToRender == 0x20)
                            {
                                charCountsToProcess.Add(noSpaceCharCount);
                                noSpaceCharCount = 0;
                            }
                            else
                            {
                                noSpaceCharCount++;
                            }
                        }
                        charCountsToProcess.Add(noSpaceCharCount);
                        if (charCountsToProcess.Count > 1)
                        {
                            Rect  boundingRect = quadBatch.getBounds(lineDesc.quadStartIndexInBatch, lineDesc.quadCount);
                            float spaceToAdd   = (lineWidth - boundingRect.width) / (charCountsToProcess.Count - 1);

                            if (spaceToAdd > 0)
                            {
                                // distribute translation to each spacing
                                int quadIndex = lineDesc.quadStartIndexInBatch;
                                int quadCount = 0;
                                for (int j = 0; j < charCountsToProcess.Count; j++)
                                {
                                    quadCount = charCountsToProcess[j];
                                    if (quadCount > 0)
                                    {
                                        // don't process first word, that stay left aligned
                                        if (j > 0)
                                        {
                                            // quadBatch.colorize ( quadIndex, 1, Color.RED ); // DEBUG : colorize first letter in red
                                            quadBatch.translate(quadIndex, quadCount, new Vector3(spaceToAdd * j, 0, 0));
                                        }
                                        quadIndex += charCountsToProcess[j];
                                    }

                                    quadIndex++;                                             // skip space char, that have not to be processed
                                }
                            }
                        }
                    }
                }
                break;
            }
        }

        if (bounds.width == -1 || bounds.height == -1)           // might have been already computed above, don't do it twice
        {
            bounds = quadBatch.getBounds();
        }

//      if ( trimTopLeftSpace ) // remove empty top left space created by glyph xoffset/yoffset
//      {
//          position.x = quadBounds.x;
//          position.y = quadBounds.y;
//          bounds.x = quadBounds.x;
//          bounds.y = quadBounds.y;
//      }

        float dx = 0;
        switch (anchor)
        {
        case TextAnchor.UpperLeft:
        case TextAnchor.MiddleLeft:
        case TextAnchor.LowerLeft:
            // dx = - bounds.width / 2;
            dx = -bounds.xMin;
            break;

        case TextAnchor.UpperCenter:
        case TextAnchor.MiddleCenter:
        case TextAnchor.LowerCenter:
            // dx = - bounds.width / 2;
            dx = -bounds.center.x;
            break;

        case TextAnchor.UpperRight:
        case TextAnchor.MiddleRight:
        case TextAnchor.LowerRight:
            // dx = - bounds.width;
            dx = -bounds.xMax;
            break;
        }

        // float dy = -( bounds.y + bounds.height );
        float dy = 0;
        switch (anchor)
        {
        case TextAnchor.UpperCenter:
        case TextAnchor.UpperLeft:
        case TextAnchor.UpperRight:
            // dy += bounds.height / 2;
            dy = -bounds.yMax;
            break;

        case TextAnchor.MiddleCenter:
        case TextAnchor.MiddleLeft:
        case TextAnchor.MiddleRight:
            // dy += bounds.height / 2;
            dy = -bounds.center.y;
            break;

        case TextAnchor.LowerCenter:
        case TextAnchor.LowerLeft:
        case TextAnchor.LowerRight:
            // dy += bounds.height;
            dy = -bounds.yMin;
            break;
        }

        quadBatch.translate(new Vector3(dx, dy, 0));
    }