Setting cursor position in system list first appearance

Freeform discussion about anything related to modding Transcendence.
Post Reply
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

I've got a couple of mods that produce full or partial system lists in custompicker screens. I'm trying to set the cursor to come up on the current system when you go to the screen for the first time, eg if you are in Sanctuary have the cursor appear on the Sanctuary listing rather than defauting to Eridani or the top of the list all the time.

The functions are easy enough. 'scrSetListCursor' and 'find'. I can reset the position with the debug screen. Remembering the cursor position is easy too and there are examples of doing this in some of the mods.

The only result I've had is using the code in <OnPaneInit> but this just locked the cursor in the one position no matter what happened. Apparently <OnPaneInit> is used on every cursor movement.

I've tried a number of the dockscreen <OnWhicheverInitiailizeEtc> areas with no success (but can't rule out coding errors).

Does anyone know where the code should go? Or if its possible at all? TIA.
Last edited by relanat on Tue Dec 20, 2016 1:24 am, edited 2 times in total.
Stupid code. Do what I want, not what I typed in!
NMS
Militia Captain
Militia Captain
Posts: 569
Joined: Tue Mar 05, 2013 8:26 am

Yes. <ListOptions> can have the attribute initialItem, which is set to a TLisp script. The game iterates through the items on the list, and the first one for which the script returns True will be selected. If none return True, the last item will be selected, though I opened a ticket suggesting it should default to the first one instead.

Note that because it's inside an XML attribute, the code has to be surrounded by quotes and thus can't contain the same type of quotes. However, you can use the other type of quotes (single inside, double outside, or maybe vice versa), or I think you can escape the quotes in the code by putting a backslash in front.

Here's an example from AutonBay.xml:

Code: Select all

	<DockScreen UNID="&dsAutonBay;"
			type=				"itemPicker"
			backgroundID=		"&rsItemListScreen;"
			>

		<ListOptions
			dataFrom=	"player"
			list=		"* +auton;"
			
			initialItem="
				(or
					(not (scrGetData gScreen 'currentAuton))
					(itmIsEqual (scrGetItem gScreen) (scrGetData gScreen 'currentAuton))
					)"
			/>
Those who are familiar with the auton bay will know this doesn't always work there, but that's due to unrelated bugs.
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

Thanks. I'll give it a try. And the info on code inside the quotes has helped elsewhere too. :D
Stupid code. Do what I want, not what I typed in!
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

Got it. So easy (relatively :lol:) when you know how!

Final code:

Code: Select all

<Dockscreen UNID="&dsD789GodTravelGalaxyDockscreen;"
			name=		"Galaxy Travel"
			type=		"customPicker"
			nestedScreen=	"true"
			>

		<List
			rowHeight="32"
			initialItem="=	(block (systemList nameList galaxyTravelList currentSystemName systemListPos)
						(setq systemList (sysGetNodes))
						(enum systemList nameList (setq galaxyTravelList (lnkAppend galaxyTravelList (sysGetProperty nameList 'name))))
						(setq currentSystemName (sysGetName (sysGetNode)))
						(setq systemListPos (find galaxyTravelList currentSystemName))
						(scrSetListCursor gScreen systemListPos)
					)
				"
			>

			(block (systemList nameList galaxyTravelList)
				(setq systemList (sysGetNodes))
				(enum systemList nameList (setq galaxyTravelList (lnkAppend galaxyTravelList (sysGetProperty nameList 'name))))
			)
		</List>
'rowHeight="32" puts about a dozen system names on the one dockscreen, compared to 4 or 5 with full size rows, which makes it a bit quicker to scroll down.
The code is duplicated outside of 'initialItem' because un'block'ing galaxyTravelList made the list add on every time you entered the dockscreen.
And I didn't need to get system names in the 'intialItem' area, nodes would have done, but the code was there so 'copy and paste' was easier.

Many thanks, NMS. I never would have found this on my own.
Stupid code. Do what I want, not what I typed in!
NMS
Militia Captain
Militia Captain
Posts: 569
Joined: Tue Mar 05, 2013 8:26 am

Well, I'm glad it works, though I'm a bit confused about how. You're not really using initialItem the way it's intended to be used, so there's definitely a simpler way.
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

NMS wrote:Well, I'm glad it works, though I'm a bit confused about how.
:lol: :lol: :lol: That statement sums up my modding. I really don't know how to write code. And the lack of documentation doesn't help along with being offline most of the time so IRC is out. I could only find three examples of 'initialItem' use so just kept trying stuff based on that until it worked.

All I do is copy someone else's code and modify it to do what I want. If there's nothing available I search the functionlist to find a function that sounds like it might do the job and give that a go. It's incredibly time-consuming but gets the job done in the end. Along with dozens of 'help please' forum topics.

I try to add numerous comments to my mods to help new modders but there is a real worry that I'm getting it wrong or making it much harder than it needs to be, thereby leading people astray.

But it is fun so that makes up for a lot of things. :)

Thanks again for your help, and everyone else as well.
Stupid code. Do what I want, not what I typed in!
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

Yes, there is indeed easier code.

Code: Select all

initialItem="=(block (
	(desiredName (sysGetProperty (sysGetNode) 'name))
	(name (scrGetListEntry gScreen))
	)

	(or (not desiredName) (eq name desiredName))
	)"
This is a modified copy of the 'initialItem' code in &dsRPGRepairArmor; in RPGCompatibility.xml. It uses the system name instead of armor segment info. Confusing layout though.

Code: Select all

(block (desiredName name)
	(setq desiredName (sysGetProperty (sysGetNode) 'name))
	(setq name (scrGetListEntry gScreen))
	(or (not desiredName)(eq name desiredName)
)
is the same I think. I still don't get it though.:lol:
Stupid code. Do what I want, not what I typed in!
NMS
Militia Captain
Militia Captain
Posts: 569
Joined: Tue Mar 05, 2013 8:26 am

Yeah, that looks good. The game selects each entry in the itemPicker one at a time and runs the initialItem code. When the code returns true, it stops and leaves that item selected. So that code returns true if the name of the item matches the name of the current system, or the current system has no name for some reason (so in that case the first item is selected instead of the last one).
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

Got it now, thanks. '(not "Lacaille")' returns Nil. So does any system name. I was thinking that '(not "Lacaille")' was True because I wanted the current system selected, but the code isn't checking the current system there, its only checking for True/Nil. (Note to self; must think more like a machine.:lol:)

I think that's so there is always a True value in there to have the first entry selected by default (to counter the "select last entry if no True value" condition of the code). Because having the last entry selected wouldn't match everything else in the game.

The following 'eq' code is then free to choose the current system.

Thanks for that. This will help in other mods as well.
Stupid code. Do what I want, not what I typed in!
Post Reply