Parcourir la source

Added textAlign vertical, horizontal and wordWrap to Text2D

Adam Bowman il y a 8 ans
Parent
commit
d8833fcce3
1 fichiers modifiés avec 175 ajouts et 19 suppressions
  1. 175 19
      canvas2D/src/Engine/babylon.text2d.ts

+ 175 - 19
canvas2D/src/Engine/babylon.text2d.ts

@@ -132,6 +132,14 @@
         }
     }
 
+    export enum TextAlign {
+        Left = 1,
+        Top,
+        Right,
+        Bottom,
+        Center
+    }
+
     @className("Text2D", "BABYLON")
     /**
      * Primitive that render text using a specific font
@@ -340,6 +348,9 @@
          * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
          * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
          * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
+         * - textAlignH: TextAlign horizontal enum (left, center, right)
+         * - textAlignV: TextAlign vertical enum (top, center, bottom)
+         * - wordWrap: if true the text will wrap inside content area
          */
         constructor(text: string, settings?: {
 
@@ -381,6 +392,9 @@
             paddingRight            ?: number | string,
             paddingBottom           ?: number | string,
             padding                 ?: string,
+            textAlignH              ?: TextAlign,
+            textAlignV              ?: TextAlign,
+            wordWrap                ?: boolean
         }) {
 
             if (!settings) {
@@ -404,6 +418,18 @@
             this._textSize           = null;
             this.text                = text;
             this.size                = (settings.size==null) ? null : settings.size;
+            
+            if(settings.textAlignH != null){
+                this.textAlignH = settings.textAlignH;
+            }
+
+            if(settings.textAlignV != null){
+                this.textAlignV = settings.textAlignV;
+            }
+
+            if(settings.wordWrap){
+                this._wordWrap = true;
+            }
 
             this._updateRenderMode();
         }
@@ -490,56 +516,181 @@
             }
 
             if (part.id === Text2D.TEXT2D_MAINPARTID) {
+
                 let d = <Text2DInstanceData>part;
                 let texture = this.fontTexture;
                 let superSampleFactor = texture.isSuperSampled ? 0.5 : 1;
                 let ts = texture.getSize();
                 let offset = Vector2.Zero();
                 let lh = this.fontTexture.lineHeight;
-                offset.y = ((this.textSize.height/lh)-1) * lh;  // Origin is bottom, not top, so the offset is starting with a y that is the top location of the text
-                let charxpos = 0;
+
                 d.dataElementCount = this._charCount;
                 d.curElement = 0;
-                for (let char of this.text) {
+
+                let lineLengths = [];
+                let charWidths = [];
+                let charsPerLine = [];
+                let charCount = 0;
+                let maxWidth = this.contentArea.width;
+                let numCharsCurrentWord = 0;
+                let widthCurrentWord = 0;
+                let numWordsPerLine = 0;
+                let text = this.text;
+                let tabWidth = this._tabulationSize * texture.spaceWidth;
+
+                for (let i = 0; i < text.length; i++) {
+                    let char = text[i];
+                    charCount++;
+                    numCharsCurrentWord++;
+                    charWidths[i] = 0;
 
                     // Line feed
                     if (char === "\n") {
+                        lineLengths.push(offset.x);
+                        charsPerLine.push(charCount - 1);
+                        charCount = 1;
                         offset.x = 0;
-                        offset.y -= texture.lineHeight;
+                        numWordsPerLine = 0;
                     }
 
-                    // Tabulation ?
+                    // Tabulation
                     if (char === "\t") {
-                        let nextPos = charxpos + this._tabulationSize;
-                        nextPos = nextPos - (nextPos % this._tabulationSize);
+                        offset.x += tabWidth;
+                        charWidths[i] = tabWidth;
 
-                        offset.x += (nextPos - charxpos) * texture.spaceWidth;
-                        charxpos = nextPos;
-                        continue;
+                        if(widthCurrentWord > 0){
+                            numWordsPerLine++;
+                        }
                     }
 
                     if (char < " ") {
+                        numCharsCurrentWord = 0;
+                        widthCurrentWord = 0;
                         continue;
                     }
 
-                    this.updateInstanceDataPart(d, offset);
-
                     let ci = texture.getChar(char);
                     offset.x += ci.charWidth;
+                    charWidths[i] = ci.charWidth;
+
+                    if (char === " ") {
+                        if(widthCurrentWord > 0){
+                            numWordsPerLine++;
+                        }
+                        numCharsCurrentWord = 0;
+                        widthCurrentWord = 0;
+                    } else {
+                        widthCurrentWord += ci.charWidth;
+                    }
+
+                    if (this._wordWrap && numWordsPerLine > 0 && offset.x > maxWidth) {
+
+                        lineLengths.push(offset.x - widthCurrentWord);
+                        charCount -= numCharsCurrentWord;
+                        let j = i - numCharsCurrentWord;
+
+                        //skip white space at the end of this line
+                        while (this._isWhiteSpaceCharHoriz(text[j])) {
+                            lineLengths[lineLengths.length - 1] -= charWidths[j];
+                            j--;
+                        }
 
-                    d.topLeftUV = ci.topLeftUV;
-                    let suv = ci.bottomRightUV.subtract(ci.topLeftUV);
-                    d.sizeUV = suv;
-                    d.textureSize = new Vector2(ts.width, ts.height);
-                    d.color = this.defaultFontColor;
-                    d.superSampleFactor = superSampleFactor;
+                        //skip white space at the beginning of next line
+                        while (this._isWhiteSpaceCharHoriz(text[i+1])) {
+                            i++;
+                            charCount++;
+                        }
 
-                    ++d.curElement;
+                        charsPerLine.push(charCount);
+                        charCount = numCharsCurrentWord;
+                        offset.x = widthCurrentWord;
+                        numWordsPerLine = 0;
+
+                    }
                 }
+
+                lineLengths.push(offset.x);
+                charsPerLine.push(charCount);
+
+                let charNum = 0;
+                let maxLineLen = 0;
+                let alignH = this.textAlignH;
+                let alignV = this.textAlignV;
+
+                offset.x = 0;
+
+                if (alignH == TextAlign.Right || alignH == TextAlign.Center) {
+                    for (let i = 0; i < lineLengths.length; i++) {
+                        if (lineLengths[i] > maxLineLen) {
+                            maxLineLen = lineLengths[i];
+                        }
+                    }
+                }
+
+                let textHeight = lineLengths.length * lh;
+                let offsetX = 0;
+                offset.y += this.size.height + textHeight - lh;
+
+                if (alignH == TextAlign.Right) {
+                    offsetX = this.size.width - maxLineLen;
+                } else if (alignH == TextAlign.Center) {
+                    offsetX = (this.size.width - maxLineLen) * .5;
+                }
+
+                offset.x += offsetX;
+
+                if (alignV == TextAlign.Bottom) {
+                    offset.y -= this.height;
+                }else if (alignV == TextAlign.Center) {
+                    offset.y -= (this.height - textHeight) * .5 + lineLengths.length * lh;
+                }else {
+                    offset.y -= lineLengths.length * lh;
+                }
+
+                for (let i = 0; i < lineLengths.length; i++) {
+                    let numChars = charsPerLine[i];
+                    let lineLength = lineLengths[i];
+
+                    if (alignH == TextAlign.Right) {
+                        offset.x += maxLineLen - lineLength;
+                    }else if (alignH == TextAlign.Center) {
+                        offset.x += (maxLineLen - lineLength) * .5;
+                    }
+
+                    for (let j = 0; j < numChars; j++) {
+                        let char = text[charNum];
+                        let charWidth = charWidths[charNum];
+
+                        this.updateInstanceDataPart(d, offset);
+                        offset.x += charWidth;
+
+                        if (!this._isWhiteSpaceCharHoriz(char)) {
+                            let ci = texture.getChar(char);
+                            d.topLeftUV = ci.topLeftUV;
+                            let suv = ci.bottomRightUV.subtract(ci.topLeftUV);
+                            d.sizeUV = suv;
+                            d.textureSize = new BABYLON.Vector2(ts.width, ts.height);
+                            d.color = this.defaultFontColor;
+                            d.superSampleFactor = superSampleFactor;
+                            ++d.curElement;
+                        }
+                        charNum++;
+                    }
+
+                    offset.x = offsetX;
+                    offset.y -= texture.lineHeight;
+                }
+
             }
             return true;
         }
 
+        private _isWhiteSpaceCharHoriz(char): boolean {
+            if(char == " " || char == "\t"){
+                return true;
+            }
+        }
+
         private _updateCharCount() {
             let count = 0;
             for (let char of this._text) {
@@ -568,5 +719,10 @@
         private _defaultFontColor: Color4;
         private _text: string;
         private _textSize: Size;
+        private _wordWrap: boolean;
+
+        public textAlignH: TextAlign;
+        public textAlignV: TextAlign;
+        
     }
 }