{
  "Name": "DrawBMFontText",
  "_id": "33b47c5a-0299-474b-9def-e6c10565d9cb",
  "Namespace": "lib.3d.generate.dependencies",
  "Description": "",
  "Inputs": [
    {
      "Name": "Color.R",
      "MetaInstanceID": "7495dd47-3d89-4961-ace6-adc720934f6f",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Color.G",
      "MetaInstanceID": "94ca2a70-6d4c-431b-8422-984e80218bc4",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Color.B",
      "MetaInstanceID": "024d45f0-89a2-4761-a3bb-0b0df4d06420",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Color.A",
      "MetaInstanceID": "f338b3d1-4eca-49ba-b9be-c3f3925ca11f",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "0",
      "Max": "1",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Text",
      "MetaInstanceID": "69847836-36a1-4c8e-a746-7443715254d1",
      "DefaultValue": {
        "Type": "Text",
        "Value": [
          "Zwei Wochen Olympische Winterspiele gehen an diesem Sonntag zu Ende. Neben der mageren deutschen ",
          "Medaillenausbeute fiel unserem Reporter vor allem auf: Es war alles nicht so schlimm wie befürchtet. ",
          "Das Apartment war fertig, die Wege kurz - und die Russen applaudierten auch den Deutschen. "
        ]
      },
      "MetaID": "c522a66e-3260-4692-b3e3-79fd0361fa3d",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "FontImage",
      "MetaInstanceID": "9d05c455-24ce-4475-97fa-4f618e2b11b9",
      "DefaultValue": {
        "Type": "Image",
        "Value": "Framefield.Core.Image"
      },
      "MetaID": "9848060d-fd84-45b0-b658-d0d531c61dab",
      "IsMultiInput": "False",
      "Relevance": "Required",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "FontInfo",
      "MetaInstanceID": "545d7770-7b3f-4c85-a348-6f49518f5786",
      "DefaultValue": {
        "Type": "Dynamic",
        "Value": "Framefield.Core.Dynamic"
      },
      "MetaID": "9701d534-b3ff-4889-a250-84aece4a7d76",
      "IsMultiInput": "False",
      "Relevance": "Required",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "KerningEnabled",
      "MetaInstanceID": "1471d5da-616e-4aa5-9815-f869d3ee2e82",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": [
        {
          "Name": "No",
          "Value": "0"
        },
        {
          "Name": "Yes",
          "Value": "1"
        }
      ]
    },
    {
      "Name": "CharacterSpacing",
      "MetaInstanceID": "f920a651-e565-4687-82ba-250a2f71c00d",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "LineHeight",
      "MetaInstanceID": "95969fc5-6ca4-4cb6-b954-ff3fcba25a90",
      "DefaultValue": {
        "Type": "Float",
        "Value": "1"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.01",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Slant",
      "MetaInstanceID": "014fdaa6-b8f4-4084-b60b-fe7d924dc33c",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "HorizontalAlign",
      "MetaInstanceID": "b13978a4-1c23-47f8-97d2-0ecd0cffa17c",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": [
        {
          "Name": "Left",
          "Value": "0"
        },
        {
          "Name": "Center",
          "Value": "1"
        },
        {
          "Name": "Right",
          "Value": "2"
        }
      ]
    },
    {
      "Name": "VerticalAlign",
      "MetaInstanceID": "d6d136cd-92eb-48a7-9cf2-898273012967",
      "DefaultValue": {
        "Type": "Float",
        "Value": "0"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-10000",
      "Max": "10000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": [
        {
          "Name": "Top",
          "Value": "0"
        },
        {
          "Name": "Middle",
          "Value": "1"
        },
        {
          "Name": "Bottom",
          "Value": "2"
        }
      ]
    }
  ],
  "Outputs": [
    {
      "Name": "Out",
      "MetaInstanceID": "02fc09bb-9166-4e07-b5c8-db8abef8afbe",
      "MetaID": "79122951-7bc4-4c68-b085-866eab828248"
    },
    {
      "Name": "LastWidth",
      "MetaInstanceID": "1cdb0463-3dff-4b53-9dda-82e13484e968",
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506"
    }
  ],
  "OperatorParts": [
    {
      "MetaInstanceID": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb",
      "MetaID": "abf37643-6e5b-48a3-aa9a-84a7c82edf89",
      "Name": "DrawBMFontTextFunc",
      "Version": "fc810825-51f6-43f0-bdce-ac86daa9086f",
      "Type": "Scene",
      "IsMultiInput": "True",
      "Script": [
        "using System;",
        "using System.Collections.Generic;",
        "using System.Linq;",
        "using System.Security.Cryptography;",
        "using BmFont;",
        "using Framefield.Core.OperatorPartTraits;",
        "using Framefield.Core.Rendering;",
        "using SharpDX;",
        "using SharpDX.Direct3D11;",
        "using SharpDX.DXGI;",
        "using Buffer = SharpDX.Direct3D11.Buffer;",
        "using MapFlags = SharpDX.Direct3D11.MapFlags;",
        "",
        "namespace Framefield.Core.IDabf37643_6e5b_48a3_aa9a_84a7c82edf89",
        "{",
        "    public class Class_DrawBMFontText : OperatorPart.Function, IMeshSupplier",
        "    {",
        "        // >>> _inputids",
        "        private enum InputId",
        "        {",
        "            ColorA = 0,",
        "            ColorB = 1,",
        "            ColorG = 2,",
        "            ColorR = 3,",
        "            Text = 4,",
        "            FontImage = 5,",
        "            FontInfo = 6,",
        "            KerningEnabled = 7,",
        "            CharacterSpacing = 8,",
        "            LineHeight = 9,",
        "            Slant = 10,",
        "            HorizontalAlign = 11,",
        "            VerticalAlign = 12",
        "        }",
        "        // <<< _inputids",
        "        ",
        "        //>>> _outputids",
        "        private enum OutputId",
        "        {",
        "            Out = 0,",
        "            LastWidth = 1",
        "        }",
        "        //<<< _outputids",
        "        ",
        "        public override void Dispose()",
        "        {",
        "            Utilities.DisposeObj(ref _mesh);",
        "        }",
        "",
        "        // IMeshSupplier",
        "        public void AddMeshesTo(ICollection<Mesh> meshes)",
        "        {",
        "            UpdateMesh(new OperatorPartContext(), OperatorPart.Connections);",
        "            meshes.Add(_mesh);",
        "        }",
        "",
        "        private string _text;",
        "        private float _characterSpacing;",
        "        private float _lineHeight;",
        "        private float _slant;",
        "        private int _horizontalAlign;",
        "        private int _verticalAlign;",
        "        ",
        "        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx)",
        "        {",
        "            ",
        "            UpdateMesh(context, inputs);                    ",
        "        ",
        "            if(outputIdx == 0) {",
        "                if(_fontImage == null || _mesh ==null)",
        "                    return context;",
        "            ",
        "                try",
        "                {                ",
        "    ",
        "                    using (var srv = new ShaderResourceView(context.D3DDevice, _fontImage))",
        "                    {",
        "                        var prevTexture = context.Texture0;",
        "                        context.Texture0 = srv;",
        "                        var prevDepthState = context.DepthStencilState;",
        "                        context.DepthStencilState = OperatorPartContext.DefaultRenderer.DisabledDepthStencilState;",
        "    ",
        "                        context.Renderer.SetupEffect(context);",
        "                        context.Renderer.Render(_mesh, context);",
        "    ",
        "                        context.DepthStencilState = prevDepthState;",
        "                        context.Texture0 = prevTexture;",
        "                    }",
        "                }",
        "                catch (Exception e)",
        "                {",
        "                    Logger.Error(this,\"error: {0}\", e);",
        "                }            ",
        "            }",
        "            else if (outputIdx == 1) {            ",
        "                context.Value = _lastWidth;",
        "            }",
        "",
        "            return context;",
        "        }",
        "        ",
        "        private float _lastWidth;",
        "",
        "        private void UpdateMesh(OperatorPartContext context, IList<OperatorPart> inputs)",
        "        {",
        "        ",
        "            if (_mesh != null && !Changed)",
        "                return;",
        "",
        "            // >>> _params",
        "            var ColorA = inputs[(int)InputId.ColorA].Eval(context).Value;",
        "            var ColorB = inputs[(int)InputId.ColorB].Eval(context).Value;",
        "            var ColorG = inputs[(int)InputId.ColorG].Eval(context).Value;",
        "            var ColorR = inputs[(int)InputId.ColorR].Eval(context).Value;",
        "            var Color = new Vector4(ColorA, ColorB, ColorG, ColorR);",
        "            var Text = inputs[(int)InputId.Text].Eval(context).Text;",
        "            var FontImage = inputs[(int)InputId.FontImage].Eval(context).Image; // Needs to be checked for null!",
        "            var FontInfo = inputs[(int)InputId.FontInfo].Eval(context).Dynamic;  // Needs to be checked for null!",
        "            var KerningEnabled = (int) inputs[(int)InputId.KerningEnabled].Eval(context).Value;",
        "            var CharacterSpacing = inputs[(int)InputId.CharacterSpacing].Eval(context).Value;",
        "            var LineHeight = inputs[(int)InputId.LineHeight].Eval(context).Value;",
        "            var Slant = inputs[(int)InputId.Slant].Eval(context).Value;",
        "            var HorizontalAlign = (int) inputs[(int)InputId.HorizontalAlign].Eval(context).Value;",
        "            var VerticalAlign = (int) inputs[(int)InputId.VerticalAlign].Eval(context).Value;",
        "            // <<< _params",
        "            ",
        "            if(FontImage == null) {",
        "                Logger.Warn(\"DrawBMFontText.FontImage missing\");",
        "                return;",
        "            }",
        "            ",
        "            if(FontInfo == null) {",
        "                Logger.Warn(\"DrawBMFontText.FontInfo missing\");",
        "                return;",
        "            }",
        "            ",
        "            var somethingChanged = false;",
        "            ",
        "            if( _horizontalAlign != (int)HorizontalAlign) {",
        "                _horizontalAlign = (int)HorizontalAlign;",
        "                somethingChanged = true;",
        "            }",
        "            ",
        "            if( _verticalAlign != (int)VerticalAlign) {",
        "                _verticalAlign = (int)VerticalAlign;",
        "                somethingChanged = true;",
        "            }",
        "            ",
        "            if( _text != Text) {",
        "                _text = Text;",
        "                somethingChanged = true;",
        "            }",
        "            ",
        "            if( _characterSpacing != CharacterSpacing) {",
        "                _characterSpacing = CharacterSpacing;",
        "                somethingChanged= true;",
        "            }",
        "            ",
        "            if( _slant != Slant) {",
        "                _slant = Slant;",
        "                somethingChanged = true;",
        "            }",
        "            ",
        "            if( _lineHeight != LineHeight) {",
        "                _lineHeight = LineHeight;",
        "                somethingChanged = true;",
        "            }",
        "            ",
        "            if( !somethingChanged ) {",
        "                return;",
        "            }",
        "",
        "",
        "            var fontImageChanged = _fontImage != FontImage;",
        "                            ",
        "            if (fontImageChanged)",
        "            {",
        "                _fontImage = FontImage;",
        "                Utilities.DisposeObj(ref _fontImageSRV);",
        "                _fontImageSRV = new ShaderResourceView(context.D3DDevice, _fontImage);",
        "            }",
        "",
        "            if(Text == \"\") ",
        "                Text = \" \"; // prevent crash error",
        "                ",
        "            int numCharactersInText = Text.Length;",
        "            int numLinesInText = Text.Split('\\n').Count();",
        "            ",
        "            _drawnText = Text;",
        "",
        "            var normal = new Vector3(0.0f, 0.0f, -1.0f);",
        "            var color = new Vector4(ColorR, ColorG, ColorB, ColorA);",
        "            var tangent = new Vector3(1.0f, 0.0f, 0.0f);",
        "            var binormal = new Vector3(0.0f, -1.0f, 0.0f);",
        "",
        "            int numQuads = numCharactersInText;",
        "",
        "            const int attributesSize = 76;",
        "            int numTriangles = numQuads*2;",
        "            var streamSize = numTriangles*3*attributesSize;",
        "",
        "            if (_mesh == null || streamSize != _mesh.NumTriangles*3*_mesh.AttributesSize)",
        "            {",
        "                Utilities.DisposeObj(ref _mesh);",
        "                using (var stream = new DataStream(streamSize, true, true))",
        "                {",
        "                    var vertices = new Buffer(context.D3DDevice, stream, new BufferDescription",
        "                                                                             {",
        "                                                                                 BindFlags = BindFlags.VertexBuffer,",
        "                                                                                 CpuAccessFlags = CpuAccessFlags.Write,",
        "                                                                                 OptionFlags = ResourceOptionFlags.None,",
        "                                                                                 SizeInBytes = streamSize,",
        "                                                                                 Usage = ResourceUsage.Dynamic",
        "                                                                             });",
        "                    _mesh = new Mesh",
        "                                         {",
        "                                             InputElements = _inputElements,",
        "                                             Vertices = vertices,",
        "                                             NumTriangles = numTriangles,",
        "                                             AttributesSize = attributesSize",
        "                                         };",
        "                }",
        "            }",
        "",
        "            DataStream vertexStream;",
        "            context.D3DDevice.ImmediateContext.MapSubresource(_mesh.Vertices, MapMode.WriteDiscard, MapFlags.None, out vertexStream);",
        "            using (vertexStream)",
        "            {",
        "                vertexStream.Position = 0;",
        "",
        "                var fontFile = (FontFile) FontInfo;",
        "                float textureWidth = fontFile.Common.ScaleW;",
        "                float textureHeight = fontFile.Common.ScaleH;",
        "                float cursorX = 0;",
        "                float cursorY = 0;",
        "                ",
        "                if((int)VerticalAlign == 1) ",
        "                {",
        "                    cursorY = fontFile.Common.LineHeight * LineHeight * (numLinesInText - 2f)/2;",
        "                }",
        "                else if( (int)VerticalAlign == 2) ",
        "                {",
        "                    cursorY = fontFile.Common.LineHeight * LineHeight * numLinesInText;",
        "                }",
        "                ",
        "                const float scale = 0.01f;",
        "                float maxWidth = float.NegativeInfinity;",
        "                numTriangles = 0;",
        "                //double lineWidthInitialized = Double.NaN;",
        "                float lineWidth = float.NaN;",
        "",
        "                for (int charIndex = 0; charIndex < _drawnText.Length; ++charIndex)",
        "                {",
        "                ",
        "                    // Compute linewidth for horizontal Alignment                    ",
        "                    if(  float.IsNaN(lineWidth )){",
        "                        ",
        "                        int lookAheadIndex = 0;",
        "                        lineWidth = 0;",
        "                                                ",
        "                        while(charIndex + lookAheadIndex < _drawnText.Length ) {",
        "                            var charForWidth = _drawnText[charIndex + lookAheadIndex];",
        "                            lookAheadIndex++;",
        "                            if(charForWidth == '\\n' || charForWidth == '\\r')",
        "                                break;",
        "                        ",
        "                            var charInfo2 = (from @char in fontFile.Chars",
        "                                            where @char.ID == (int) charForWidth",
        "                                            select @char).SingleOrDefault();",
        "                            var width = charInfo2.Width;",
        "    ",
        "                            float kerning2 = 0.0f;",
        "                            ",
        "                            if (KerningEnabled > 0.5f && charIndex + lookAheadIndex < _drawnText.Length - 1 && _drawnText[charIndex+lookAheadIndex+1] != '\\n')",
        "                            {",
        "                                var nextCharInfo2 = (from @char in fontFile.Chars",
        "                                                    where @char.ID == (int) _drawnText[charIndex + lookAheadIndex + 1]",
        "                                                    select @char).SingleOrDefault();",
        "                                if (nextCharInfo2 != null)",
        "                                {",
        "                                    var kerningInfo2 = (from d in fontFile.Kernings",
        "                                                       where d.First == charInfo2.ID",
        "                                                       where d.Second == nextCharInfo2.ID",
        "                                                       select d).SingleOrDefault();",
        "                                    if (kerningInfo2 != null)",
        "                                    {",
        "                                        kerning2 = kerningInfo2.Amount;",
        "                                    }",
        "                                }",
        "                            }",
        "                            lineWidth += kerning2;",
        "                            lineWidth += charInfo2.XAdvance;",
        "                            lineWidth += CharacterSpacing;    ",
        "                        }",
        "                        if(HorizontalAlign == 1) {",
        "                            cursorX-= lineWidth/2 - CharacterSpacing/2;",
        "                        }",
        "                        else if(HorizontalAlign == 2) {",
        "                            cursorX-= lineWidth;",
        "                        }",
        "                        if( lineWidth > maxWidth) {",
        "                            maxWidth = lineWidth;",
        "                        }",
        "                    }",
        "                    ",
        "                ",
        "                    var charToDraw = _drawnText[charIndex];",
        "                    if (charToDraw == '\\n')",
        "                    {",
        "                        cursorY -= fontFile.Common.LineHeight * LineHeight;",
        "                        cursorX = 0;",
        "                        lineWidth = float.NaN;",
        "                        continue;",
        "                    }",
        "                    var charInfo = (from @char in fontFile.Chars",
        "                                    where @char.ID == (int) charToDraw",
        "                                    select @char).SingleOrDefault();",
        "                    if (charInfo == null)",
        "                    {",
        "                        continue;",
        "                    }",
        "",
        "                    float uLeft = charInfo.X/textureWidth;",
        "                    float vTop = charInfo.Y/textureHeight;",
        "                    float uRight = (charInfo.X + charInfo.Width)/textureWidth;",
        "                    float vBottom = (charInfo.Y + charInfo.Height)/textureHeight;",
        "",
        "                    var SizeWidth = charInfo.Width;",
        "                    var SizeHeight = charInfo.Height;",
        "",
        "                    float bottom = cursorY + charInfo.YOffset;",
        "                    float top = bottom + SizeHeight;",
        "                    float left = cursorX + charInfo.XOffset;",
        "                    float right = left + SizeWidth;",
        "                    float slantTop = Slant * 0.001f * SizeHeight;",
        "",
        "                    bottom *= scale;",
        "                    top *= scale;",
        "                    left *= scale;",
        "                    right *= scale;",
        "                    ",
        "",
        "                    // tri 1 vert 1",
        "                    vertexStream.Write(new Vector4(right + slantTop, top, 0, 1));",
        "                    vertexStream.Write(normal);",
        "                    vertexStream.Write(color);",
        "                    vertexStream.Write(new Vector2(uRight, vTop));",
        "                    vertexStream.Write(tangent);",
        "                    vertexStream.Write(binormal);",
        "",
        "                    // tri 1 vert 2",
        "                    vertexStream.Write(new Vector4(right, bottom, 0, 1));",
        "                    vertexStream.Write(normal);",
        "                    vertexStream.Write(color);",
        "                    vertexStream.Write(new Vector2(uRight, vBottom));",
        "                    vertexStream.Write(tangent);",
        "                    vertexStream.Write(binormal);",
        "",
        "                    // tri 1 vert 3",
        "                    vertexStream.Write(new Vector4(left, bottom, 0, 1));",
        "                    vertexStream.Write(normal);",
        "                    vertexStream.Write(color);",
        "                    vertexStream.Write(new Vector2(uLeft, vBottom));",
        "                    vertexStream.Write(tangent);",
        "                    vertexStream.Write(binormal);",
        "",
        "                    // tri 2 vert 1",
        "                    vertexStream.Write(new Vector4(left, bottom, 0, 1));",
        "                    vertexStream.Write(normal);",
        "                    vertexStream.Write(color);",
        "                    vertexStream.Write(new Vector2(uLeft, vBottom));",
        "                    vertexStream.Write(tangent);",
        "                    vertexStream.Write(binormal);",
        "",
        "                    // tri 2 vert 2",
        "                    vertexStream.Write(new Vector4(left + slantTop, top, 0, 1));",
        "                    vertexStream.Write(normal);",
        "                    vertexStream.Write(color);",
        "                    vertexStream.Write(new Vector2(uLeft, vTop));",
        "                    vertexStream.Write(tangent);",
        "                    vertexStream.Write(binormal);",
        "",
        "                    // tri 2 vert 3",
        "                    vertexStream.Write(new Vector4(right + slantTop, top, 0, 1));",
        "                    vertexStream.Write(normal);",
        "                    vertexStream.Write(color);",
        "                    vertexStream.Write(new Vector2(uRight, vTop));",
        "                    vertexStream.Write(tangent);",
        "                    vertexStream.Write(binormal);",
        "",
        "                    float kerning = 0.0f;",
        "                    if (KerningEnabled > 0.5f && charIndex < _drawnText.Length - 1)",
        "                    {",
        "                        var nextCharInfo = (from @char in fontFile.Chars",
        "                                            where @char.ID == (int) _drawnText[charIndex + 1]",
        "                                            select @char).SingleOrDefault();",
        "                        if (nextCharInfo != null)",
        "                        {",
        "                            var kerningInfo = (from d in fontFile.Kernings",
        "                                               where d.First == charInfo.ID",
        "                                               where d.Second == nextCharInfo.ID",
        "                                               select d).SingleOrDefault();",
        "                            if (kerningInfo != null)",
        "                            {",
        "                                kerning = kerningInfo.Amount;",
        "                                //Logger.Info(this, \"Kerning for {0} and {1}: {2}\", charInfo.ID, nextCharInfo.ID, kerningInfo.Amount);",
        "                            }",
        "                        }",
        "                    }",
        "                    cursorX += kerning;",
        "                    cursorX += charInfo.XAdvance;",
        "                    cursorX += CharacterSpacing;",
        "                    numTriangles += 2;",
        "                }",
        "                _mesh.NumTriangles = numTriangles; // set real drawn number of triangles",
        "                _lastWidth = maxWidth;            }",
        "            context.D3DDevice.ImmediateContext.UnmapSubresource(_mesh.Vertices, 0);",
        "",
        "",
        "            Changed = false;",
        "        }",
        "",
        "        private Mesh _mesh;",
        "        private Texture2D _fontImage;",
        "        private ShaderResourceView _fontImageSRV;",
        "        private string _drawnText = string.Empty;",
        "",
        "        private readonly InputElement[] _inputElements = {",
        "                                                             new InputElement(\"POSITION\", 0, Format.R32G32B32A32_Float, 0, 0),",
        "                                                             new InputElement(\"NORMAL\", 0, Format.R32G32B32_Float, 16, 0),",
        "                                                             new InputElement(\"COLOR\", 0, Format.R32G32B32A32_Float, 28, 0),",
        "                                                             new InputElement(\"TEXCOORD\", 0, Format.R32G32_Float, 44, 0),",
        "                                                             new InputElement(\"TANGENT\", 0, Format.R32G32B32_Float, 52, 0),",
        "                                                             new InputElement(\"BINORMAL\", 0, Format.R32G32B32_Float, 64, 0)",
        "                                                         };",
        "",
        "    }",
        "}"
      ],
      "AdditionalAssemblies": []
    }
  ],
  "Operators": [],
  "Connections": [
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "02fc09bb-9166-4e07-b5c8-db8abef8afbe"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "f338b3d1-4eca-49ba-b9be-c3f3925ca11f",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "024d45f0-89a2-4761-a3bb-0b0df4d06420",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "94ca2a70-6d4c-431b-8422-984e80218bc4",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "7495dd47-3d89-4961-ace6-adc720934f6f",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "69847836-36a1-4c8e-a746-7443715254d1",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "9d05c455-24ce-4475-97fa-4f618e2b11b9",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "545d7770-7b3f-4c85-a348-6f49518f5786",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "1471d5da-616e-4aa5-9815-f869d3ee2e82",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "f920a651-e565-4687-82ba-250a2f71c00d",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "95969fc5-6ca4-4cb6-b954-ff3fcba25a90",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "014fdaa6-b8f4-4084-b60b-fe7d924dc33c",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "b13978a4-1c23-47f8-97d2-0ecd0cffa17c",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "d6d136cd-92eb-48a7-9cf2-898273012967",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "c52f2f0a-303a-4d06-94bc-b45c1d35d5cb",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "1cdb0463-3dff-4b53-9dda-82e13484e968"
    }
  ]
}