Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Clickable word in a text.

Discussion in 'Immediate Mode GUI (IMGUI)' started by KevS, Jul 18, 2011.

  1. KevS

    KevS

    Joined:
    Apr 21, 2010
    Posts:
    51
    Hi people !
    Here is my problem : I would like to display a text (easy :cool:) but some of the words have to be clickable :? (or more generally interactive)

    So my idea was to display the text with a set of "GUILayouted" Labels and Buttons with the same style.
    Something like that :
    Code (csharp):
    1.  
    2. GUILayout.BeginArea(new Rect(10, 10, Screen.width - 10, 200));
    3.  
    4. GUILayout.BeginHorizontal();
    5. GUILayout.Label("This is the first part of the text before the clickable word ");
    6. GUILayout.Button("FIRST CLICKABLE WORD ");
    7. GUILayout.Label("a second part of text before an other word ");
    8. GUILayout.Button("SECOND CLICKABLE WORD ");
    9. GUILayout.Label("This is the end of text.");
    10. GUILayout.EndHorizontal();
    11.  
    12. GUILayout.EndArea();
    13.  
    The result : (word wrap of Label style is disabled and the Button style is not yet the same style.)



    It's almost what I want, the problem is to have a new line when needed. It try to play with BeginHorizontal/Vertical, some GUILayoutOption like MaxWidth... can't find a way to have a new line.

    So what do you think ? (I could compute the length of all the parts of the text and then according to the area width define manually my new lines but I'm not sure that is a smart solution)
    Maybe there is also a better solution (I was thinking about something completely different : my text as a texture and I could compare the position of the mouse on it to check if the cursor is over a interactive word ...)

    Thanks !
    Kevin.
     

    Attached Files:

  2. KevS

    KevS

    Joined:
    Apr 21, 2010
    Posts:
    51
    I find a better solution !!!! :D

    Here is THE function : GUIStyle.GetCursorStringIndex

    With these function (and a bit of code ^^), i will be able to know on wich word my mouse is over, and trigger events if needed :D

    First test :
    Code (csharp):
    1.  
    2. public GUISkin skin;
    3. public Rect textArea;
    4. public int cursorIndex;
    5. public string myText;
    6.  
    7. void Start ()
    8.     {
    9.         textArea = new Rect (0, 0, 500, 30);
    10.         myText = "My entire text to display.";
    11.     }
    12.  
    13. void OnGUI ()
    14.     {
    15.         GUI.skin = skin;
    16.         GUI.Label (textArea, myText);
    17.         cursorIndex = GUI.skin.GetStyle ("MyLabel").GetCursorStringIndex (textArea, new GUIContent (myText), Event.current.mousePosition);
    18.     }
    19.  
     
  3. solmyr-fr

    solmyr-fr

    Joined:
    Jun 18, 2009
    Posts:
    24
    Hi. It's funny because I wanted to do the exact same think only 10 hours after you posted this thread. I had a problem with GUILayout event with horizontal/vertical options in an area to constraint each label/button to render just after the previous one.

    So... I did it using the normal GUI with Rect ... To determine the correct position, I did this (if this can help people wo want to do the same) :
    - first step (inside Start) : parse a text file with markup (for instance "this is a link to <link="http://www.google.fr">google</link> to be parsed."). It fills a List<Element> where Element is an abstract class (instanced as ElementText or ElementLink). an element contains its text and a Rect for its position (and additionnal stuff depending of the type).
    - second step (inside OnGUI but just for the first frame to avoid some computations) : for each Element (it doesn't matter what type it is), you must split its text in words (using the Split string function). Then you recreate several Element in another list and for each one you add words one by one to make its text to fill only one line of your whole text area. To do so you'll have to use GUIStyle.CalcSize() so that's why these computation must be inside OnGUI (but only in the first frame using a boolean value).

    It was quite painfull to code and I still have to correct minor bugs but it works :)
     
  4. djennin2

    djennin2

    Joined:
    Dec 4, 2016
    Posts:
    4
    Hey KevS, I know this is a bit of gravedigging... and it's likely that you never visit these forums anymore; but, in the off-chance you do, would you mind explaining how this function might work if you need it for multiple strings of text?

    I don't know if I'm explaining this correctly, so I'll try an example: I'm building an interactive fiction police procedural. I would like to have certain words "clickable". As the player reads the story, when they come across the word "gun" they can click on that to get more information (tooltip, separate text area, ect.) about the murder weapon. This is to simulate the process of investigation in my game.

    Now, as it sits, your method would work if all of my story was contained to a single body of text... the problem is that I built a state machine to tell my story. So, each line of the story is a different state and a different "body of text".

    I'm rather new to Unity and C# and this looks like my best hope of getting the result I'm looking for IF I can figure out how to get it to work.
     
  5. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    The OnGUI method of creating GUI is the old way of laying out GUI. It still works, but it's not getting worked on - the new way of doing things is through the Canvas system introduced about two years ago. Which is a year after OP last logged on, according to their profile :p


    That being said, if you're still doing this in the OnGUI way - what's the exact issue? With a state machine setup, you'd still have a specific object that displays text through it's OnGUI. when you detect a mouse click, you could ask that component where the current mouse position is in relation to it's text, and work with that.
     
  6. Ruchmair

    Ruchmair

    Joined:
    Sep 20, 2015
    Posts:
    544
    We use this method.

    Code (CSharp):
    1. GUILayout.Button("Text","Label");
    2.