[SOLVED][GUI] Toggle screens using Esc key?

When you click the Objectives button it automatically closes the Recall button, and vice versa. What makes this possible? I don’t see anything obvious that would control this behavior in the GUI screens themselves.

Also, what determines whether a screen can be closed using the Esc key?

Thanks!

[edit]

I created a new screen and button, and it’s the same issue. The button works, but the Esc key will not deactivate the screen.

[edit]

I just noticed that a third screen I created can be closed using the Esc key. WTF?!

Since nobody seems to know the answers to your questions, here are my guesses :

  • For the Objective list and recall screens, I honestly have no idea. The only element that might be worth checking is that they share the same anchor and UI_ToggleScreen might be doing something with that to hide/show concurrent UI elements in that case :

Anchor_Binds = {
pivotY = “Subtitle_LocationBottomCenter”,
pivotX = “Subtitle_LocationBottomCenter”,
},

  • For the Esc key, I think this might be because they are derived from the RmWindow type, which has close buttons. Those perhaps capture the Esc key.

Sorry if this wasn’t any help!

I forgot to say that the Speech Recall screen does not close via the Esc key. So I don’t think it’s because both screens share the anchor binds or RmWindow type in common.

Concerning this issue, I’m currently doing some tests, and it seems the Esc key closes a screen when there is a button named “m_btnCancel” in it. I’m pretty sure that just having an invisible frame with this name in your screen would activate this behavior.

EDIT : it’s more complicated than that. It’s seems that the game is detecting a specific pattern in the UI code. Continuing my investigations.

EDIT2 : see next post

Behavior confirmed.

You need 2 things :

  • an element named m_btnCancel (not necessarily a Button/TextButton, can be a Frame)

  • an action associated to its onMouseClicked param

Example :

{
	type = "Frame",
	name = "m_btnCancel",
	visible = 0,
	ignored = 1, --we don't want the Frame to take some space, so ignore it (only works if invisible)
	onMouseClicked ="UI_HideScreen('Manual'); UI_ShowScreen('NewMainMenu', ePopup)",
},

By adding this to my screen, I was able to close it by pressing the ESC key, without any real close button present/visible in the screen.
It seems the action(s) associated with the element named m_btnCancel is/are triggered when the ESC key is pressed.
With this, I suppose it would also be possible to do any other action(s), like opening another screen or whatever, when pressing the ESC key.

@Pouk because teasing :stuck_out_tongue:

1 Like

Right. :slight_smile:

It’s not working for me. Here’s my button.

		-- CLOSE
		{
			type = "TextButton",
			name = "m_btnCancel",
			buttonStyle = "FEButtonStyle1_Alert_Outlined_Chipped",
			Layout =
			{
				pivot_XY = { 0.5, 0.0 },
				pos_XY = {x = 0.5, y = 0.0, xr="par", yr="px",},
				size_WH = {w = 1.0, h = STD_BUTTON_HEIGHT, wr = "par", hr = "scr"},
			},	
			helpTip = "Close the squad menu screen.",
			helpTipTextLabel = "txtLblHELPTEXT",
			Text =
			{
				text = "Close",
			},
			onMouseClicked = "print('it worked!')",
		},

It’s not printing “it worked!” ?

The screen is not closing when pressing the Esc key.

[edit]

Oops.

Perfectly normal, as you didn’t set it in the onMouseClicked param ! :stuck_out_tongue:

As said before, the ESC key calls the action(s) associated in the m_btnCancel button, so if you only have a print in it, it will only print :wink:

2 Likes

Sorry, I meant it’s not printing when I hit the Esc key. Or doing anything, depending on how I have it configured.

				-- CLOSE
				{
					type = "TextButton",
					name = "m_btnCancel",
					buttonStyle = "FEButtonStyle1_Alert_Outlined_Chipped",
					Layout =
					{
						pivot_XY = { 0.5, 0.0 },
						pos_XY = {x=0.5, y=0.0, xr="par", yr="px",},
						size_WH = {w = NAVIGATION_BUTTON_WIDTH, h = STD_BUTTON_HEIGHT, wr = "scr", hr = "scr"},
					},	
					helpTip = "Close the map screen.",
					helpTipTextLabel = "txtLblHELPTEXT",
					Text =
					{
						text = "Close",
					},
					onMouseClicked = "print('It is working.')",
				},

It’s not printing except when I click on the button using the mouse.

[edit]

This was from an in-game menu, FYI. Your code looks like it is from a frontend menu, if it makes a difference.

[edit]

The file I copied my code from is called “sectormapscreen.lua” and can be downloaded along with the rest of my mod here:

I also checked the default “objectiveslist.lua”. It has also no “m_btnCancel” button, yet closes properly using Esc key.

[edit]

I tried adding the following line to “keybindings.lua”, but it overrides the default behavior instead of extending it.

{ 177,	CloseLotsOfWindows,								INKE_KeyDown,	0,	"Close Them",		{ ESCKEY } },

I would need to figure out a list of all windows that need to be closed and duplicate the behavior. It’s likely I would overlook something.

Could be why it’s working in mine and not yours, yes (damn hardcoding !).

There is a button named m_btnAccept in “objectiveslist.lua” which closes the screen. Try perhaps the same kind of trick, but by naming the element in your screen m_btnAccept ?

I tried that without luck. Further, both “objectiveslist.lua” and “speechrecall.lua” have an m_btnAccept button, but Esc only closes the former.

[edit]

The game seems to remember the order in which windows were opened, and closes them in the reverse order. I will have to emulate that behavior somehow too, versus just closing them all at the same time with one key press.

Is it possible to track when a screen was opened, and in what order multiple screens were opened? Thanks.

I would say yes, by appending to a text file when a screen opens with onShow, and modifying said files when onHide triggers, so you would have a live image of the order in which screens has been shown.

EDIT : I think all the onShow/onHide/OnMouseEnter/etc… are in the same scope, so you could perhaps use a simple array variable which you would modifiy on the go.

EDIT2 : after thinking, I seem to remember that each screen has its own scope, so the solution in my first edit is not sure to work.

1 Like

In my screen I have:

onOpen =
[[
	say_something = "Hi!"
	print(say_something .. " First!")
]],

In “keybindings.lua” I have:

{ 18,	[[print(say_something .. " Second!")]],								INKE_KeyDown,	1,	"$5316",		{ ESCKEY }},

The “First!” print is not happening at all. The “Second!” print causes the game to complain about concatenating a nil value. Not sure what is going on here.

[edit]

I searched through the “Homeworld2.big” contents and could not find any instances of onOpen being used. I found two instances of onOpening, but they are commented out. Are you sure you got the parameter names right?

Oups, my bad !

It’s onShow/onHide, not onOpen/onClose, sorry for that !

The message “concatenating a nil value” is because the “say_something” variable is not defined in the scope (certainly different between the onOpen and the keybinding one. EDIT : NOPE ^^).

Just so you know, nil is the “value” of a variable when it has not been assigned anything yet (the variable doesn’t exist).
And it’s not possible to concatenate a string with a non-existing variable. Thus the error message you have.

1 Like

It works! And it seems the screen and “keybindings.lua” do in fact share the same scope. Haven’t tested yet if multiple different screens share the same scope as well.

1 Like

Good to know ! It’s been a long time, I wasn’t sure if it was the case ^^