Search Unity

C# How to clear one line of a Text object after it has x lines / is full?

Discussion in 'Scripting' started by Abelabumba, Mar 6, 2015.

  1. Abelabumba

    Abelabumba

    Joined:
    Jan 14, 2015
    Posts:
    45
    So I want to have some kind of news bar in my game that shows recent messages.

    Code (CSharp):
    1. public class NewsBar : MonoBehaviour
    2. {
    3.     public Text shownText;
    4.     private string wholeText;
    5.     private string datum;
    6.  
    7.     public void addText(string newInput)
    8.     {
    9.         datum = Date.datum;
    10.         newInput = (datum + " " + newInput);
    11.         wholeText = (wholeText + "\n" + newInput);
    12.         shownText.text = wholeText;
    13.     }
    14. }
    This works like I want it to: I can do

    Code (CSharp):
    1. newsBar.addText("yo");
    and it shows the ingame date plus the text, if I do this multiple times it'll look like this:

    19.10.1984 yo
    19.10.1984 yo
    20.10.1984 yo

    and so on, but once I get to the bottom of the text object, new lines don't appear, obviously.
    So how can I

    a) check if the text box is going to be full before sending in the next message and
    b) delete the topmost line?

    As you've probably guessed I'm new to this, so please bear with me if the answer is obvious.
     
  2. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Store them in a List<string> and remove old entries as necessary.
     
  3. knr_

    knr_

    Joined:
    Nov 17, 2012
    Posts:
    258
    Hi Abelabumba,

    I am not sure if this is exactly what you are looking for, but it may point you to a solution. Good luck!

    (I have not tested this code so it may not work the way I am expecting it to).

    Use a C# queue.

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public Text shownText;
    6. private string wholeText;
    7. private string datum;
    8.  
    9. public Int32 m_MaxLines = 4;
    10. private Queue m_Inputs;
    11.  
    12. public class Example : MonoBehaviour
    13. {
    14.    public void Awake()
    15.    {
    16.       m_Inputs = new Queue();
    17.    }
    18.  
    19.    public void AddText(String newInput)
    20.    {
    21.       if (m_Inputs.Count >= m_MaxLines)
    22.       {
    23.          m_Inputs.Dequeue();
    24.       }
    25.  
    26.       m_Inputs.Enqueue(newInput);
    27.      
    28.       UpdateText();
    29.    }
    30.  
    31.    public void UpdateText()
    32.    {
    33.       wholeText = "";
    34.  
    35.       foreach ( Object obj in m_Inputs)
    36.       {
    37.          String strDate = obj as String;
    38.          datum = Date.dateum;
    39.          strDate = (datum + " " + strDate);
    40.          wholeText = (wholeText + "\n" + strDate );
    41.       }
    42.  
    43.       shownText.text = wholeText;
    44.    }
    45. }
     
    Last edited: Mar 6, 2015
  4. Cynikal

    Cynikal

    Joined:
    Oct 29, 2012
    Posts:
    122
    I'd split it with the separator of \n then you can delete the specific array..the first [0] or the last [myinteger.count - 1]
     
  5. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Why on earth would you use a collection that isn't type-safe?

    Code (csharp):
    1.  
    2. List<string> input = new List<string>();
    3.  
    4. void AddText(string newInput)
    5. {
    6.     if (input.Count == maxInput)
    7.     {
    8.         input.RemoveAt(input.Count - 1);
    9.     }
    10.     input.Add(newInput);
    11. }
    12.  
     
  6. knr_

    knr_

    Joined:
    Nov 17, 2012
    Posts:
    258
    If the only code path for adding things to the queue is a String, then you don't need to worry about it being type-safe. You are essentially guaranteeing what is going in to the queue is a string and what is coming out of the queue is a string.

    Either way, both solutions should work, which means it comes down to a question of preference over things like that.
     
    Last edited: Mar 6, 2015
  7. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    I couldn't disagree more. The only way to "guarantee" what goes in and comes out is to use a type-safe collection that only accepts strings. Not to mention saving the performance (and hassle) of having to cast every item in that collection when it comes time to use it.
     
  8. knr_

    knr_

    Joined:
    Nov 17, 2012
    Posts:
    258
    Cool. Agree to disagree. :)
     
  9. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Only if you like doing things the more verbose, less performant, more error-prone way.
     
  10. knr_

    knr_

    Joined:
    Nov 17, 2012
    Posts:
    258
    Everyone is entitled to their opinion, including you. :)

    I would suggest that before you accuse the code I wrote of having the possibility of adding something that isn't a string to the queue to go back and look at it though (the entire code). Its not worth debating it with you anymore.
     
  11. _met44

    _met44

    Joined:
    Jun 1, 2013
    Posts:
    633
    Kelso is right.

    And FYI, you can type queues... use Queue<string> and you won't be having this conversation with a not so nice tone :p
     
  12. knr_

    knr_

    Joined:
    Nov 17, 2012
    Posts:
    258
    Yes, you can type queues, which is what I should have done (thanks!). But the code as is won't add anything to the queue but strings... and Kelso suggested that queues are a collection that are not / cannot be type safe...

    "Why on earth would you use a collection that isn't type-safe?"

    It could have been an issue of misunderstanding the statement. Either way, its done. He wrote a great implementation that would work. Mine works too and would be better if it was templated (sp?) as you suggested. :)
     
  13. _met44

    _met44

    Joined:
    Jun 1, 2013
    Posts:
    633
    No but tonight at 4am when OP will be sleep coding he might want to add a method that performs an operation on the strings and end up with unexpected values because he didn't feed his non typed queue with the proper value. (and compiler didn't warn him he should go to sleep)
     
  14. knr_

    knr_

    Joined:
    Nov 17, 2012
    Posts:
    258
    Absolutely, that is a risk that you take. Making a mistake like that depends on a lot of variables about the programmer him/herself. Again, templating it to use a specific type is definitely the way to go if you choose to use the queue.

    You must really hate Python. :p
     
  15. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    I never said that. I said the one you're using isn't. Queue isn't type-safe, but Queue<T> is. I'm being hard on you because you're insinuating to someone who is an admitted beginner that introducing ambiguity into their code is a matter of preference and your code is safe simply on the basis of not currently exposing its weakness.
     
  16. Abelabumba

    Abelabumba

    Joined:
    Jan 14, 2015
    Posts:
    45
    Thanks everyone; I got it working with your help. Final code:

    Code (CSharp):
    1.     public List<string> list = new List<string>();
    2.     public Text shownText;
    3.     private string wholeText;
    4.     private string datum;
    5.     private int maxLines = 4;
    6.     private string strDate;
    7.  
    8.     public void addText(string newInput)
    9.     {
    10.         if (list.Count == maxLines)
    11.         {
    12.             list.RemoveAt(0);
    13.         }
    14.         datum = Date.datum;
    15.         newInput = (datum + " " + newInput);
    16.         Debug.Log(newInput);
    17.         list.Add(newInput);
    18.         UpdateText();
    19.     }
    20.  
    21.     public void UpdateText()
    22.     {
    23.         wholeText = "";
    24.         foreach (string s in list)
    25.         {
    26.             strDate = s as string;
    27.             wholeText = (wholeText + "\n" + strDate);
    28.         }
    29.         shownText.text = wholeText;
    30.     }
    31. }
    I had to change some small things to get it to work as I want it; notably list.RemoveAt(list.Count-1) to list.RemoveAt(0); so that it removes the topmost line and moving the whole date affair up to addText(string newInput) from UpdateText() because it would otherwise update / show the same date for all entries in the list.

    Thanks again everyone, I still feel a bit like it's cheating to ask the community stuff like this :)

    Edit: Oh, I almost forgot - is there a (not super involved) way to actually check when the box is going to be full? The int maxLines = x works pretty well but I have to be conservative with it, because some messages can actually have multiple lines, therefore I will have lots of white space most of the time which isn't very pretty.
     
    Last edited: Mar 6, 2015
  17. knr_

    knr_

    Joined:
    Nov 17, 2012
    Posts:
    258
    Glad you got it working and no, its not cheating :).

    I'm sorry that you had to see the spat between Kelso and I. In all respects, he is making the right case, especially for a beginner. If you do end up working with languages that are not strongly typed like Python or Lua you run into the situations that Kelso mentioned, and getting experience making such mistakes because of it will make you a better programmer - and using loosely typed data structures no longer are an issue because you simply don't make those mistakes anymore - which is why I'm being hard on him too, but in the end his case for your situation is a lot stronger than mine is. :)

    Good luck with your project!

    (and a tip of my hat to Kelso) :)
     
  18. Abelabumba

    Abelabumba

    Joined:
    Jan 14, 2015
    Posts:
    45
    Don't be sorry, first of all I'm new to programming but not to the internet, can't get much more harmless than that.
    Secondly it has been informative as well, so it's all good.
     
  19. Abelabumba

    Abelabumba

    Joined:
    Jan 14, 2015
    Posts:
    45
    I've promised my GF no more coding tonight so I'll try it tomorrow but one idea I have to make it a bit better is counting the letters in newInput and splitting it into multiple lines if needed, without the date in its subsequent lines. That way the maxLines will actually represent the number of lines and not the number of messages.

    Still not ideal though, because different characters take up different amounts of horizontal space, but oh well.
     
  20. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    You might be better off doing something that scrolls and focusing the scroll to the bottom when a new message comes in
     
    Abelabumba likes this.
  21. Abelabumba

    Abelabumba

    Joined:
    Jan 14, 2015
    Posts:
    45
    Lol, you're obviously right, I'll do that tomorrow.