Author Topic: Feature: Force upper case  (Read 6419 times)

dlewis

  • Guest
Feature: Force upper case
« on: May 28, 2012, 08:42:26 PM »
This is a simple post which describes how I went about implementing a feature to force a UI Label to display text in upper case. It is intended to be a suggestion for a future feature of NGUI and a guide for other who wish to implement this feature themselves. Hopefully someone can find this useful.

Written for C#.

First of all, there is an extremely handy inbuilt function with the string library called ToUpper() which does what you think, converts a string to upper case, this is exactly what we need.

First of all we need to add a few variables to the UILabel class so we can mark labels as 'Force caps/upper case'

  1. // In UILabel.cpp
  2.  
  3. [HideInInspector][SerializeField] string mText_NonCaps = "";
  4. [HideInInspector][SerializeField] bool mForceCaps = false;

mForceCaps is pretty simple, just a check box so we can mark as UI label as upper case only. mText_NonCaps is used to preserve the old string so that we can dynamically switch between the upper case string and the original string that has been entered.

For example. In a text box you might enter the string "Awesome String". Ticking the Force Caps button will convert that to "AWESOME STRING". Because we have stored the original string ("Awesome String") we can simply untick the Force Caps and the text will revert to the original, non upper case version (If you made a designer re-enter all the text if they pressed it by accident they would NOT be happy).

Next we need to expose the toggle to the inspector.

  1. // In UILabelInspector.cpp
  2.  
  3. override protected bool OnDrawProperties ()
  4. {
  5.     // Existing code here
  6.  
  7.     bool forceCaps = EditorGUILayout.Toggle("Force Caps", mLabel.ForceCaps);
  8.     if (forceCaps != mLabel.ForceCaps) { RegisterUndo(); mLabel.ForceCaps = forceCaps; }
  9.  
  10.     return true;
  11. }

This just places a tick box in the UILabel inspector. If you've been following this your code will not compile as forceCaps is a private variable. I left the accessor to last as it contains most of the logic we care about. When changing the tick box we need to store the original string and then make the current upper case OR restore the original string.

  1. // In UILabel.cpp
  2.  
  3. public bool ForceCaps
  4. {
  5.         get { return mForceCaps; }
  6.         set
  7.         {
  8.                 // If we are going to force caps then save the text so we can restore it
  9.                 if (value)
  10.                 {
  11.                         mText_NonCaps = mText;
  12.                         mText = mText.ToUpper();
  13.                 }
  14.                 else // Set the text back to the non caps value
  15.                 {
  16.                         mText = mText_NonCaps;
  17.                         mText_NonCaps = "";
  18.                 }
  19.  
  20.                 mForceCaps = value;
  21.         }
  22. }

Luckily I added comments so this is very self explanitory. If we are ticking the box (Wanting to force upper case) then we save the original string to the mText_NonCaps variable then make the text upper case with the handy C# function I meantioned at the start. If we are unticking the box then we want to restore the original value and I clear the non caps value just to be nice.

The final step is to modify the text entry so it will respect the setting when entering text.

  1. // In UILabel.cpp. This is a modification of an existing function
  2.  
  3. public string text
  4. {
  5.         get
  6.         {
  7.                 return mText;
  8.         }
  9.         set
  10.         {
  11.                 if (value != null && mText != value)
  12.                 {
  13.                         if (mForceCaps)
  14.                         {
  15.                                 mText_NonCaps = value;
  16.                                 mText = ((string)value).ToUpper();
  17.                         }
  18.                         else
  19.                         {
  20.                                 mText = value;
  21.                         }
  22.                         hasChanged = true;
  23.                 }
  24.         }
  25. }

This simply saves the original value and converts the new one to upper case if that option is ticked, if not it will just enter it as normal.

There is an oddity with Unity (or my code) where if you tick Force Caps and start typing it will display as normal text in the inspector but in the game/scene it will be upper case. When you click out of the text edit box then the text in the inspector will update to be upper case.

I hope this has been helpful to at least one person. If you have any questions about this just post!

Nicki

  • Global Moderator
  • Hero Member
  • *****
  • Thank You
  • -Given: 33
  • -Receive: 141
  • Posts: 1,768
    • View Profile
Re: Feature: Force upper case
« Reply #1 on: May 29, 2012, 02:21:39 AM »
It seems to me to be a little overkill, when you can have whichever script fill out your myLabel.text = "blah blah", just do myLabel.text = "blah blah".ToUpper() and handle it in your own code, since UIlabel is just a "visualizer" of text, so to speak.

I can see the value if you use the inspector view to fill out the text, sure, but it still feels like overkill.

dlewis

  • Guest
Re: Feature: Force upper case
« Reply #2 on: May 29, 2012, 06:44:56 PM »
The reason I did it like this is because now it's out of my hands, the UI designer can mark any label they want to be upper case and it will just work instead of getting me to go into every script and marking it at .ToUpper (and a lot of stuff is generic which makes it more complex).

The more power you give to the designers the better.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Feature: Force upper case
« Reply #3 on: May 29, 2012, 06:57:16 PM »
So here's the obvious question.

Why not just ask your designer to type in caps when he needs caps?

dlewis

  • Guest
Re: Feature: Force upper case
« Reply #4 on: May 29, 2012, 06:59:52 PM »
Why not just ask your designer to type in caps when he needs caps?

Most of the values for the UI comes from our game database.

So for example we have a list of players, in one screen we want the player names to be all upper case yet in other locations we don't want that. This isn't a small project so the more control we can have the better ;)
« Last Edit: May 29, 2012, 07:01:29 PM by dlewis »

StridingDragon

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 53
    • View Profile
Re: Feature: Force upper case
« Reply #5 on: January 25, 2013, 08:01:53 PM »
I think this is an incredibly useful function. I'm a bit surprised you do not see value in it, Aren. It happens all the time in game development that you retrieve text information from a back end that then may need to be converted to upper case for screen output. Whether it is user input, character names, location names, or other things, this adds tremendous functionality to the text output.

I'm reluctant to make these changes because it will mean I have to redo them ever time there is an NGUI code revision. I think I may look into either creating a separate helper script for this or perhaps an new class that derives from UILabel.

hellobard

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 22
    • View Profile
Re: Feature: Force upper case
« Reply #6 on: March 10, 2014, 03:54:37 PM »
I'd like to revive this feature request.

I'm using NGUI's excellent Localize function with a CSV database, and the only way for me to get a label in upper case is to actually change my localization database. In most cases, I don't want my text in uppercase when I pull something from the CSV, but in the cases I do, it's incredibly cumbersome to have to hack this. It would be a simple drop down list for the UILabel (Upper case, lower case, none) and very useful for us designers.

While I'm at it, maybe the UILabel could get a feature for having shadows AND outlines at the same time. Also a mod of the outlines to decide if the outline goes outside, inside or center like in Photoshop would be incredibly useful. Obviously I could do this with a bitmap font, but I've got quite a few atlases already and would love to be able to save memory this way.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Feature: Force upper case
« Reply #7 on: March 10, 2014, 08:22:25 PM »
Re: shadows & outline:

http://www.youtube.com/watch?v=FsKrZAMrkXU -- approximately 2/3rds of the way to the end.

Re: caps and whatnot: I don't want to clutter the label inspector any more than it already is. If you need this kind of functionality, you can easily do it just by creating a simple localizator and using it instead of UILocalize:
  1. using UnityEngine;
  2.  
  3. public class UILocalizeInCaps : MonoBehaviour
  4. {
  5.     public string key;
  6.  
  7.     void Start() { OnLocalize(); }
  8.  
  9.     void OnLocalize ()
  10.     {
  11.         GetComponent<UILabel>().text = Localization.Get(key).ToUpper();
  12.     }
  13. }

hellobard

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 22
    • View Profile
Re: Feature: Force upper case
« Reply #8 on: March 11, 2014, 04:00:23 AM »
Ah fantastic, thank you very much :)
I wouldn't say that an option for uppercase would make it cluttered. It's like the text tool in Photoshop, it's got everything I need within the same size as the UILabel ;)