Search Unity

DrawText on Texture2D?

Discussion in 'Scripting' started by IzzySoft, Dec 31, 2013.

  1. IzzySoft

    IzzySoft

    Joined:
    Feb 11, 2013
    Posts:
    376
    hi All... me once more :)

    Trying to find a workaround to reading the Font materials Texture, so i can use it to draw each of the texture Characters to my own Texture2D...

    Code (csharp):
    1.  
    2.     public static void DrawText(this Texture2D tx, string sText, Font myFont )
    3.     {
    4.         CharacterInfo ci;
    5.         char[] cText = sText.ToCharArray();
    6.        
    7.         Material fontMat = myFont.material;
    8.         Texture2D fontTx = (Texture2D) fontMat.mainTexture;
    9.  
    10.         int x, y, w, h;
    11.         int posX = 10;
    12.        
    13.         for( int i = 0; i < cText.Length; i++ )
    14.         {
    15.             myFont.GetCharacterInfo( cText[i], out ci, 32 );
    16.            
    17.             x = (int) ((float) fontTx.width * ci.uv.x);
    18.             y = (int) ((float) fontTx.height * (ci.uv.y + ci.uv.height));
    19.             w = (int) ((float) fontTx.width * ci.uv.width);
    20.             h = (int) ((float) fontTx.height * (-ci.uv.height));
    21.            
    22.             Color[] cChar = fontTx.GetPixels( x, y, w, h );
    23.            
    24.             tx.SetPixels( posX, 10, w, h, cChar );
    25.            
    26.             posX += (int) ci.width;
    27.         }
    28.     }
    29.  
    And calling it...

    Code (csharp):
    1.  
    2. ...
    3.     public Font myFont;
    4.  
    5.     void Start ()
    6.     {
    7.         int texSize = 256;     
    8.         Texture2D tex = new Texture2D(texSize, texSize, TextureFormat.ARGB32, false, true);
    9.         tex.alphaIsTransparency = true;
    10.  
    11.         tex.DrawText( "Hello World!", myFont);
    12.  
    13.         tex.Apply();
    14.         renderer.material.mainTexture = tex;
    15.     }
    16.  
    ... but i keep getting this Error:



    i dont think i can change it from the Inspector:



    So.... is there a workaround?
    note: I would really like to be able to use the Font Texture that Unity generates....
    ...But i'm open to suggestions. ;)

    thanks all,
    Izzy.
     
    z3nth10n likes this.
  2. IzzySoft

    IzzySoft

    Joined:
    Feb 11, 2013
    Posts:
    376
    No workarounds? :(
     
  3. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
  4. IzzySoft

    IzzySoft

    Joined:
    Feb 11, 2013
    Posts:
    376
    Thank you for replying

    It seems .isReadable is part of the TextureImporter.

    I hope i dont have to write any kind of AssetPostprocessor.OnPostprocessTexture for the TrueTypeFontImporter... do i? :/

    I dont recall seeing a TrueTypeFontImporter - PostProcessor option anywhere.

    But, your other hint helped some.
    http://answers.unity3d.com/questions/485695/truetypefontimportergenerateeditablefont-does-not.html



    That seems to exttact the Material and the Texture... but Erros out now in my version of Unity 4.3.1f1, says it failed to recognize the font type.
    Oh well.. at least it didnt error out before extracting the Texture :D
     
  5. IzzySoft

    IzzySoft

    Joined:
    Feb 11, 2013
    Posts:
    376
    Sweet...

    I got the W to flip to the right.
    I got the 'y' to align to the base.
    and this is what it looks like so far. :D



    Alpha 8 i assume is black and white? with black being the alpha mask?

    Ok. I just need to composite the Color[] pixels for each letter with the Color[] pixels it will replace in the destination and it should look about right. :D Fingers crossed.
     
  6. IzzySoft

    IzzySoft

    Joined:
    Feb 11, 2013
    Posts:
    376
    I got the Composting showing and the results look like this for each Update():



    I know this isnt very good for performance, but I just wanted to see how fast (or slow) it performed. 33% CPU usage. 38 or so FPS.

    And i'm not even using Color32 yet. Not optimized. :)
     
    Last edited: Jan 3, 2014
  7. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Whyyyy
    setpixel is not very runtime friendly
     
  8. IzzySoft

    IzzySoft

    Joined:
    Feb 11, 2013
    Posts:
    376
    Only out of curiosity. ;)
    I've never done anything like this in Unity... testing! :D

    Anyways using SetPixels32 seems to run twice as fast on this PC.

    And i would like to see which is the best approach.
    I was thinking, a Multi-Material approach would work good.

    Ex: if i wanted to make a left to right scrolling text ticker for Breaking News?
    Material 1 would have the background texture.
    Material 2 would have the DrawText texture (called only once in a while) ...
    ... and scrolling would be animated using UV offset?!

    I have no clue if this will work, since this is new to me, but should work in theory. :)
     
    Last edited: Jan 3, 2014
  9. IzzySoft

    IzzySoft

    Joined:
    Feb 11, 2013
    Posts:
    376
    Is everyone else wrapping their GUI controls like this too? :(

    Code (csharp):
    1.  
    2. // ---- MyControl.cs ----
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. [System.Serializable]
    7. public class MyControl : Object
    8. {
    9.     private GUIContent _Content = new GUIContent();
    10.     private Rect _Content_Area = new Rect(0,0,0,0);
    11.     private Rect _Content_Area_Previously = new Rect(0,0,0,0);
    12.     private string _Content_Text = "";
    13.     private Texture _Content_Texture = null;
    14.     private string _Content_Tooltip = "";
    15.     private string _Content_Style_Name = "";
    16.     private GUIStyle _Content_Style = null;
    17.     private bool _Autofit = false;
    18.     private int _ControlID = 0;
    19.     private bool _IsDraggable;
    20.     private Rect _DraggableArea;
    21.     private EventType _EventType;
    22.     private bool _Visible = true;
    23.     private Vector2 _MouseDown_Offset = new Vector2( 0, 0 );
    24.  
    25.     // Constructor
    26.     public MyControl( )
    27.     {
    28.         _Content = new GUIContent();
    29.         Init();
    30.     }
    31.  
    32.     // Constructor
    33.     public MyControl( string label )
    34.     {
    35.         _Content = new GUIContent( label );    
    36.         Init();
    37.     }
    38.  
    39.     // Constructor
    40.     public MyControl( Texture icon )
    41.     {
    42.         _Content = new GUIContent( icon );
    43.         Init();
    44.     }
    45.  
    46.     // Constructor
    47.     public MyControl( string label, Texture icon )
    48.     {
    49.         _Content = new GUIContent( label, icon );      
    50.         Init();
    51.     }
    52.  
    53.     // Constructor
    54.     public MyControl( string label, Texture icon, string tooltip )
    55.     {
    56.         _Content = new GUIContent( label, icon, tooltip );
    57.         Init();
    58.     }
    59.  
    60.     private void Init()
    61.     {
    62.         // ...
    63.     }
    64.  
    65.     public void DrawButton()
    66.     {
    67.         if( _Visible == false )
    68.             return;
    69.  
    70.         CheckIfContentStyleWasCreated();
    71.  
    72.         CheckIfContentSizeChangedViaUser();
    73.  
    74.         HandleEvents();
    75.  
    76.         //GUI.Button( _Content_Area, _Content, _Content_Style_Name );
    77.  
    78.     }
    79.  
    80.     private void CheckIfContentSizeChangedViaUser()
    81.     {
    82.         bool bChanged = _Content_Area.width !=_Content_Area_Previously.width || _Content_Area.height !=_Content_Area_Previously.height;
    83.  
    84.         if( bChanged )
    85.         {
    86.             if( _Autofit )
    87.                 CalculateContentArea();
    88.  
    89.             _Content_Area_Previously.width = _Content_Area.width;
    90.             _Content_Area_Previously.height = _Content_Area.height;
    91.         }
    92.     }
    93.  
    94.     private void CheckIfContentStyleWasCreated()
    95.     {
    96.         if( _Content_Style_Name == "" )
    97.             _Content_Style_Name = "button";
    98.        
    99.         if( _Content_Style == null )
    100.         {
    101.             CreateContentStyle();
    102.         }
    103.     }
    104.  
    105.     private void CreateContentStyle()
    106.     {
    107.         _Content_Style = new GUIStyle( _Content_Style_Name );
    108.         CalculateContentArea();
    109.     }
    110.  
    111.     private void CalculateContentArea()
    112.     {
    113.         Vector2 size = _Content_Style.CalcSize( _Content );
    114.         _Content_Area.width = size.x;
    115.         _Content_Area.height = size.y;
    116.     }
    117.  
    118.     private void HandleEvents()
    119.     {
    120.         if( _ControlID == 0 )
    121.             _ControlID = GUIUtility.GetControlID( _Content, FocusType.Native );
    122.        
    123.         _EventType = HandleMouseEvents();
    124.  
    125. //      if( _EventType == EventType.ignore )
    126. //          _EventType = HandleKeyboardEvents();
    127.     }
    128.  
    129.     private EventType HandleMouseEvents()
    130.     {
    131.         EventType eType = Event.current.GetTypeForControl( _ControlID );
    132.  
    133.         switch( eType )
    134.         {
    135.         case EventType.mouseDown:          
    136.             if( _Content_Area.Contains( Event.current.mousePosition ) )
    137.             {              
    138.                 GUIUtility.hotControl = _ControlID;
    139.                 _MouseDown_Offset.x = Event.current.mousePosition.x - _Content_Area.x;
    140.                 _MouseDown_Offset.y = Event.current.mousePosition.y - _Content_Area.y;
    141.                 Event.current.Use();               
    142.                 return EventType.mouseDown;            
    143.             }
    144.             break;
    145.            
    146.         case EventType.mouseUp:        
    147.             if( GUIUtility.hotControl != _ControlID )          
    148.                 return EventType.ignore;
    149.            
    150.             GUIUtility.hotControl = 0;     
    151.             Event.current.Use();
    152.            
    153.             if( _Content_Area.Contains( Event.current.mousePosition ) )
    154.                 return EventType.mouseUp;
    155.             else
    156.                 return EventType.ignore;
    157.            
    158.         case EventType.mouseDrag:      
    159.             if( GUIUtility.hotControl == _ControlID )              
    160.             {
    161.                 Event.current.Use();
    162.  
    163.                 if( _IsDraggable )
    164.                 {
    165.                     _Content_Area.x = Mathf.Clamp( Event.current.mousePosition.x - _MouseDown_Offset.x, _DraggableArea.x, _DraggableArea.x + _DraggableArea.width - 1 );
    166.                     _Content_Area.y = Mathf.Clamp( Event.current.mousePosition.y - _MouseDown_Offset.y, _DraggableArea.y, _DraggableArea.y + _DraggableArea.height - 1 );
    167.                 }
    168.  
    169.                 return EventType.mouseDrag;
    170.             }
    171.             else
    172.                 return EventType.ignore;
    173.            
    174.         case EventType.repaint:
    175.             _Content_Style.Draw( _Content_Area, _Content, _ControlID );
    176.            
    177.             if( _Content_Area.Contains( Event.current.mousePosition ) )
    178.                 return EventType.mouseMove;
    179.             else               
    180.                 return EventType.repaint;
    181.         }
    182.        
    183.         if( _Content_Area.Contains( Event.current.mousePosition ) )
    184.             return EventType.mouseMove;
    185.         else
    186.             return EventType.ignore;
    187.     }
    188.    
    189.     public GUIContent Content
    190.     {
    191.         get {
    192.             return _Content;
    193.         }
    194.  
    195.         set {
    196.             _Content = value;
    197.         }
    198.     }
    199.  
    200.     public Rect ContentArea
    201.     {
    202.         get {
    203.             return _Content_Area;
    204.         }
    205.        
    206.         set {
    207.             _Content_Area = value;
    208.         }
    209.     }
    210.  
    211.     public float Width
    212.     {
    213.         get {
    214.             return _Content_Area.width;
    215.         }
    216.        
    217.         set {
    218.             _Content_Area.width = value;
    219.         }
    220.     }
    221.  
    222.     public float Height
    223.     {
    224.         get {
    225.             return _Content_Area.height;
    226.         }
    227.        
    228.         set {
    229.             _Content_Area.height = value;
    230.         }
    231.     }
    232.  
    233.     public float X
    234.     {
    235.         get {
    236.             return _Content_Area.x;
    237.         }
    238.        
    239.         set {
    240.             _Content_Area.x = value;
    241.         }
    242.     }
    243.  
    244.  
    245.     public float Y
    246.     {
    247.         get {
    248.             return _Content_Area.y;
    249.         }
    250.        
    251.         set {
    252.             _Content_Area.y = value;
    253.         }
    254.     }
    255.  
    256.     public string StyleName
    257.     {
    258.         get {
    259.             return _Content_Style_Name;
    260.         }
    261.        
    262.         set {
    263.             _Content_Style_Name = value;
    264.         }
    265.     }
    266.  
    267.     public GUIStyle Style
    268.     {
    269.         get {
    270.             return _Content_Style;
    271.         }
    272.        
    273.         set {
    274.             _Content_Style = value;
    275.         }
    276.     }
    277.  
    278.     public bool Autofit
    279.     {
    280.         get {
    281.             return _Autofit;
    282.         }
    283.        
    284.         set {
    285.             _Autofit = value;
    286.         }
    287.     }
    288.    
    289.     public int ControlID
    290.     {
    291.         get {
    292.             return _ControlID;
    293.         }
    294.        
    295. //      set {
    296. //          _ControlID = value;
    297. //      }
    298.     }
    299.  
    300.     public bool IsDraggable
    301.     {
    302.         get {
    303.             return _IsDraggable;
    304.         }
    305.  
    306.         set {
    307.             _IsDraggable = value;
    308.         }
    309.     }
    310.  
    311.     public Rect DraggableArea
    312.     {
    313.         get {
    314.             return _DraggableArea;
    315.         }
    316.        
    317.         set {
    318.             _DraggableArea = value;
    319.         }
    320.     }
    321.  
    322.     public EventType TypeOfEvent
    323.     {
    324.         get {
    325.             return _EventType;
    326.         }
    327.        
    328. //      set {
    329. //          _EventType = value;
    330. //      }
    331.     }
    332.  
    333. }
    334.  


    and usage:

    Code (csharp):
    1.  
    2. // ---- MyControlTest.cs ----
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. [RequireComponent( typeof( GUILayer ) )]
    7. public class MyControlTest : MonoBehaviour
    8. {
    9.     public MyControl[] Controls = new MyControl[6];
    10.     public string[] ControlTypes = new string[] { "box", "toggle", "label", "button", "textfield", "window" };
    11.  
    12.     void Start ()
    13.     {
    14.         SetupControlls();
    15.     }
    16.  
    17.     void OnGUI()
    18.     {
    19.         for(int i=0; i<Controls.Length; i++ )
    20.             Controls[i].DrawButton();
    21.     }
    22.  
    23.     void SetupControlls()
    24.     {
    25.         for(int i=0; i<Controls.Length; i++ )
    26.         {
    27.             Controls[i] = new MyControl( "Button " + i.ToString() );
    28.             Controls[i].StyleName = ControlTypes[i];
    29.             Controls[i].X = 160;
    30.             Controls[i].Y = 30 * i ;
    31.             Controls[i].Autofit = true;
    32.             Controls[i].IsDraggable = true;
    33.             Controls[i].DraggableArea = new Rect( 0, 0, Screen.width-1, Screen.height-1 );
    34.         }
    35.     }
    36.  
    37. }
    38.  
     
  10. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    One plane object with a background texture
    One textmesh that moves left to right
    ?
     
  11. IzzySoft

    IzzySoft

    Joined:
    Feb 11, 2013
    Posts:
    376
    Last edited: Jan 6, 2014
  12. Orion

    Orion

    Joined:
    Mar 31, 2008
    Posts:
    261
    Cool stuff!

    Tip to simplify your wrapping - instead of writing this:
    Code (csharp):
    1. private GUIStyle _Content_Style;
    2. public GUIStyle Style
    3.     {
    4.        get {
    5.             return _Content_Style;
    6.         }        
    7.         set {
    8.             _Content_Style = value;
    9.         }
    10.     }
    you can use automatic accessors, like this:
    Code (csharp):
    1. public GUIStyle Style { get; private set; }
    Hope that helps :)
     
    GilesDMiddleton likes this.
  13. Mr_Mow

    Mr_Mow

    Joined:
    Jan 7, 2016
    Posts:
    4
  14. z3nth10n

    z3nth10n

    Joined:
    Nov 23, 2013
    Posts:
    55
    Last edited: Oct 24, 2020