Jump to content

Tooltips in uGUI


Recommended Posts

I've been looking for a way to add tooltips to my mod. And I found a relatively easy way to do it.

var tooltip = myGameObject.AddComponent<KSP.UI.TooltipTypes.TooltipController_Text> ();
tooltip.SetText ("My Awesome Tooltip");

But there is one problem: TooltipController needs a prefab. I looked around in the game and found out that all controller instances in the game have the very same prefab (this field could just as well be static, and save me a lot of trouble... wink wink :) ). While I could just take a random controller and copy a prefab from it, that would be hacky and unreliable.

Could someone tell me the proper way of obtaining this prefab? Preferably, the way the stock GUI elements do it.

Link to comment
Share on other sites

Oh wow, I've just been setting the tooltipText properties of my buttons and hoping in vain it would somehow start working. If I'm able to get real tooltips working this way, then a big thanks to you from me and anyone that uses my mod for a big usability improvement!

Link to comment
Share on other sites

looking at the code all the tooltipcontrollers do use a prefab and there is no generic one statically defined that you could call on currently (makes notes to see how hard that would be to adjust for the future)

for now if you want to use the stock tooltip then I would recommend grabbing the prefab from an existing TooltipController_Text object (it will even localize the string when spawning the tooltip if you set its text to be a loclization key)

 

Link to comment
Share on other sites

48 minutes ago, TriggerAu said:

for now if you want to use the stock tooltip then I would recommend grabbing the prefab from an existing TooltipController_Text object

Ok, I'll do that for now. If anybody wants to follow the way of 80lvl hackers, here's the code I use:

static KSP.UI.TooltipTypes.Tooltip_Text _prefab = null;
static KSP.UI.TooltipTypes.Tooltip_Text prefab {
  get {
    if (_prefab == null) {
      foreach (var comp in GameObject.FindObjectsOfType<KSP.UI.TooltipTypes.TooltipController_Text> ()) {
        if (comp.prefab != null) {
          _prefab = comp.prefab;
          return _prefab;
        }
      }
    }
    return _prefab;
  }
}

Be sure to run this code after the stock GUI is done initializing.

Link to comment
Share on other sites

2 hours ago, Morse said:

Ok, I'll do that for now. If anybody wants to follow the way of 80lvl hackers, here's the code I use:

Be sure to run this code after the stock GUI is done initializing.

And... what do you do with the prefab property after that? Assign it to tooltip.prefab? Pretend I'm 5 years old or know very little about Unity.

EDIT: Confirmed! That works. This toolkit just gets curiouser and curiouser.

Edited by HebaruSan
Link to comment
Share on other sites

I'm trying to add this to a DialogGUIButton, which I think doesn't get a GameObject till later, so I'm deferring it with OnUpdate:

		public static Tooltip_Text tooltipPrefab = GameObject.FindObjectOfType<TooltipController_Text>()?.prefab;

			gb.OnUpdate = () => {
				if (gb.uiItem != null) {
					SetTooltip(gb.uiItem, tooltip);
					gb.OnUpdate = () => {};
				}
			};

		public static GameObject SetTooltip(GameObject gameObj, string tooltip)
		{
			TooltipController_Text tt = (gameObj?.GetComponent<TooltipController_Text>() ?? gameObj?.AddComponent<TooltipController_Text>());
			if (tt != null) {
				tt.textString = tooltip;
				tt.prefab = tooltipPrefab;
			}
			return gameObj;
		}

... and it seems to work! Now to see whether my app launcher icon has an exposed GameObject...

(Previous question about error message deleted; I think FindObjectOfType was finding the same TooltipController_Text object that I just created, which naturally didn't have a prefab defined yet.)

Edited by HebaruSan
Link to comment
Share on other sites

7 hours ago, HebaruSan said:

I think FindObjectOfType was finding the same TooltipController_Text object that I just created

And that was exactly the reason why I used the iterator in my example :)

7 hours ago, HebaruSan said:

TooltipController_Text tt = (gameObj?.GetComponent<TooltipController_Text>() ?? gameObj?.AddComponent<TooltipController_Text>()); 

There is a function called GetOrAddComponent for precisely such a case.

As for the GameObject for the AppLauncherButton... I don't see one easily exposed. Maybe I'm missing something. But keep in mind that stock buttons don't use tooltips, they use the full-fleshed windows that are anchored to the buttons (see ApplicationLauncherButton.GetAnchor ())

Link to comment
Share on other sites

I've been using my own tooltip implementation (it's rather pitiful that Unity hasn't come up with a native tooltip solution) based on a modified version of one found in the Unity UI extensions. I ran into the same issues with trying to deal with the tooltip prefab and decided to make my own, as it allows for more flexibility. It obviously doesn't help much if you aren't using a full Unity-editor UI, but it works for me.

This script is attached to the Tooltip prefab that you make in Unity (it mostly controls positioning the tooltip). And this script is attached to whatever you want a tooltip for (it mostly controls the mouseEnter and mouseExit events to spawn the tooltip).

 

If you want to get a KSP tooltip prefab it's best to try to find another prefab that has it, rather than waiting for some other window to load. For instance, if you can find the KerbalPortrait prefab (which would require finding the KerbalPortraitGallery prefab...). That way you aren't reliant on something else being loaded, since some things might not be loaded in different game types, or may be effected by mods.

This is what I've been doing with my not-yet-released deltaV mod to get some of the Contract App sprites and UI elements. If you can't find a prefab somewhere, you can always just resort to checking the Resources class; see hereResources.FindObjectsOfTypeAll is different from GameObject.FindObjectsOfType, as the latter only looks for currently active objects, while the former searches through all of the loaded Resources (eg. it would work in the Main Menu, or in a sandbox game where the Contracts App is never actually loaded).

 

As for getting GameObjects, it doesn't matter if one is exposed or not, you can figure out the object hierarchy with Debug Stuff and then use GetComponent or one of its variants to find what you need.

Link to comment
Share on other sites

1 hour ago, DMagic said:

I've been using my own tooltip implementation (it's rather pitiful that Unity hasn't come up with a native tooltip solution) based on a modified version of one found in the Unity UI extensions. I ran into the same issues with trying to deal with the tooltip prefab and decided to make my own, as it allows for more flexibility. It obviously doesn't help much if you aren't using a full Unity-editor UI, but it works for me.

This script is attached to the Tooltip prefab that you make in Unity (it mostly controls positioning the tooltip). And this script is attached to whatever you want a tooltip for (it mostly controls the mouseEnter and mouseExit events to spawn the tooltip).

If you want to get a KSP tooltip prefab it's best to try to find another prefab that has it, rather than waiting for some other window to load. For instance, if you can find the KerbalPortrait prefab (which would require finding the KerbalPortraitGallery prefab...). That way you aren't reliant on something else being loaded, since some things might not be loaded in different game types, or may be effected by mods.

Is there anything akin to UISkinManager.GetPrefab("UIButtonPrefab") for TooltipController_Text, to get the right prefab directly? It seems like that would be the right answer. (Again with these wonderfully self documenting interfaces where I'm left wondering, "What values am I allowed to plug in there, and is there a list of them somewhere?")

1 hour ago, DMagic said:

As for getting GameObjects, it doesn't matter if one is exposed or not, you can figure out the object hierarchy with Debug Stuff and then use GetComponent or one of its variants to find what you need.

Sounds dirty, but I guess the chance of SQUAD swapping out ApplicationLauncherButton's implementation for one not based on GameObject would be close enough to 0%.

Link to comment
Share on other sites

1 hour ago, HebaruSan said:

Is there anything akin to UISkinManager.GetPrefab("UIButtonPrefab") for TooltipController_Text, to get the right prefab directly? It seems like that would be the right answer. (Again with these wonderfully self documenting interfaces where I'm left wondering, "What values am I allowed to plug in there, and is there a list of them somewhere?")

Well that's basically the problem I was alluding to. That method returns prefabs for UI Skins, there are other similar methods that can be used for some other prefabs (I think AssetBase has one for a bunch of random prefabs), but if you need one for specific type then you're stuck looking through each class the might have a public reference or going for one of the brute force methods.

1 hour ago, HebaruSan said:

Sounds dirty, but I guess the chance of SQUAD swapping out ApplicationLauncherButton's implementation for one not based on GameObject would be close enough to 0%.

It's not dirty, it's just how Unity works. Basically everything is an arrangement of GameObjects. It's possible that the specific hierarchy might change for some reason in an update, but unlikely, and generally easily fixed.

Link to comment
Share on other sites

58 minutes ago, DMagic said:

Well that's basically the problem I was alluding to. That method returns prefabs for UI Skins, there are other similar methods that can be used for some other prefabs (I think AssetBase has one for a bunch of random prefabs), but if you need one for specific type then you're stuck looking through each class the might have a public reference or going for one of the brute force methods.

So, we're borrowing a prefab from some stock code. How did that code get it?

Link to comment
Share on other sites

Assigned in Unity. If you ever run into anything (a reference to a prefab, a value for a primitive type, a UI image, etc...) that appears to be already assigned then it was probably done so in the Unity editor.

Link to comment
Share on other sites

8 minutes ago, DMagic said:

Assigned in Unity. If you ever run into anything (a reference to a prefab, a value for a primitive type, a UI image, etc...) that appears to be already assigned then it was probably done so in the Unity editor.

Grumble, grumble. (Thanks!)

UJuHw3F.gif

Link to comment
Share on other sites

15 hours ago, Morse said:

There is a function called GetOrAddComponent for precisely such a case.

Google finds that under something called "Unify," not "Unity," and sure enough it doesn't compile for me. I think I can get by without a custom extension library for this one thing.

Link to comment
Share on other sites

I maybe have found a less hackish way of obtaining the prefab. Like this:

static KSP.UI.TooltipTypes.Tooltip_Text _prefab = null;
static KSP.UI.TooltipTypes.Tooltip_Text prefab {
  get {
    if (_prefab == null) {
      _prefab = AssetBase.GetPrefab<KSP.UI.TooltipTypes.Tooltip_Text> ("Tooltip_Text");
    }
    return _prefab;
  }
}

@TriggerAu, can you tell me how likely this is gonna break in the future? :)

Link to comment
Share on other sites

On 6/1/2017 at 7:45 PM, Morse said:

I maybe have found a less hackish way of obtaining the prefab. Like this:


static KSP.UI.TooltipTypes.Tooltip_Text _prefab = null;
static KSP.UI.TooltipTypes.Tooltip_Text prefab {
  get {
    if (_prefab == null) {
      _prefab = AssetBase.GetPrefab<KSP.UI.TooltipTypes.Tooltip_Text> ("Tooltip_Text");
    }
    return _prefab;
  }
}

@TriggerAu, can you tell me how likely this is gonna break in the future? :)

Ill check it today and get back to you. I think that should be very static yes

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...