[WIP] MenuV - An alternative Menu system for GTAV... hopefully.
So this thread has been forked from another thread concerning the performance of Benny's mod. https://forums.gta5-mods.com/topic/6251/script-rewrite-benny-s-motorworks-sp-mod-into-a-asi-performence-increased-script/36
The issue arose about the performance impact of NativeUI and after some brief yet eye-opening testing, I decided to take on the challenge of doing something about it. I'm not modifying NativeUI, this is a completely independent project that may or may not succeed.
I haven't done anything quite like this before, so there are a whole host of unknowns. But like everything else I take on, I will give it my best shot and accept that whilst I may succeed, I may equally fail. No promises, no guarantees... just my honest efforts and frequent ramblings. Probably wise to read the origin thread before continuing as this thread starts kinda in the middle of things... this just seemed like the best place to break out of that thread.
Well this is proving to be a challenge but I think I am making progress. Populating the menu with various types seems to work and varying amounts or menu items seems to work. I currently only have the ListItem working properly but I think this video shows, performance is looking promising. Based on the FPS counter in the top-left corner anyway.
The ListItem is probably the most function heavy item of them all... until I add my ImageListItem that is... more on that much later. Still a long way to go and this is definitely causing some headaches, mainly because certain aspects of how this needs to be written leave me scratching my head repeatedly.
Pretty much 90% of all calculations are done outside the Draw() functions, so that side of things is about as fast as it can be. Anyway, just thought I would post this as a small progress demo. All I can say is this is going to require patience from anyone waiting for it to happen.
The text you see at the bottom is the text in the mod using the menu, this was just to show me that the event handling was passing values back out of the menu system properly. Event handling is one of my biggest hurdles, delegates just confuse the heck out of me.
Been working on a bit of the cosmetic side of things so far today. A bit of digging and rewriting got me a string length function, that means I can right-justify text strings... something that was essential for the List items.
I have also added an adaptive scrollbar down the right hand side of the menu. In its current form, it is merely an indicator as to where you are relative to the full menu length. I don't like menus where you have no idea where you are, because you can end up wrapping from bottom to top (or vice versa) when you least expect it. When I get mouse control added, I want it to work as a proper scrollbar. This is optional and if turned off, the menu will appear the full width of the banner.
So after adding all this extra cosmetic functionality, the current FPS hit is as shown below. The images are paired Left - Right.
Just another short video showing pretty much all functions now working as they should (on a single menu that is). All items send event triggers back to the main mod successfully. Items can be enabled and disabled and unlike NativeUI, disabled items are skipped instead of just being drawn in grey. You can see in the video that enabling and disabling items results in real-time changes to the menu,.
With all this now running, I am still seeing zero FPS drops, even with this nine item menu. I am now starting to wonder if the NativeUI insistence on "Looking nice in all resolutions" is part of the problem it has. It's a menu, it simply has to work and it has to use very few resources when it does. If that means that it doesn't look quite as nice in every resolution, then I'll take that over a 50fps drop.
You can also see an item I also added to my own customised version of NativeUI, which is an IncDec item. This is similar in function to the Windows NumericUpDown control. You can set a maximum value, a minimum value and a step value that the value increments and decrements by. I find it a really useful control. The top IncDec has a range of 0 - 10 in .25 step size. The bottom one has a range of 0 - 100 in steps of 5.
What I am going to do very soon, is transfer my ongoing Auto-Snap mod over to this menu system, so I can get a proper sense of how well this is functioning.
Anyway, here's the short video.
@LeeC2202 Well, I must say, I am impressed with what are you doing so far. And yes, for some users Native UI, didn't register any hit on FPS, but for most of the users including me, it just kills the FPS. And an updated library was needed so good going there. Goodluck. (:
@ashishcw I wonder how many people were like me though, where they were playing with VSync on and simply didn't notice the FPS hit because their game always remained above the VSync threshold? I never gave it much thought, then again, the only mods I use with NativeUI in them are the test mods I build, which is why I am able to run a custom NativeUI.
But it makes me wonder if all those people not having problems turned their VSync off, would they see the problem like I did? I don't know... all I know is that there was no logical reason for something this simple, to have an impact at the level NativeUI had.
There's a still a fair way to go with this and some of the remaining tasks could prove to be the ones that cause me the biggest problems... and ultimately be the ones that cause this to fail. We shall see...
@LeeC2202 WOW nice work dude! Do you done this since i started this thread?
And will your plugin work with script mods that uses NativeUI?
@MrGTAmodsgerman Yeah, I had never even thought about this until a few days ago. Unfortunately, I am a slow coder, so it's not going to be a quick process with me driving it. I wish I could write code as fast as others but it just doesn't happen. I keep expecting someone to post a "Here's a new faster, more efficient version" way ahead of me... that's what usually happens. Part of my problem is I get caught up on how it looks (perils of being an artist I'm afraid) so that can be a distraction. I can sit tweaking things pixels at a time for ages, to get them to look right.
At the moment, I am writing it in a way that suits my way of thinking but my ultimate goal, is to make it compatible with existing NativeUI calls as well. Not sure how possible that will be and it will still need mods to be rebuilt against this library instead of NativeUI... that could be a major hurdle as I suspect most people won't want to do that. All I can do is try and give people an easier option than a total rewrite, the rest is up to them.
@MrGTAmodsgerman It probably would if he named everything the same as NativeUI (assembly, namespace, class, functions, etc.) (if that's actually how it works, not exactly sure).
@Jitnaught You're probably right with that but that treads on very dangerous ground... I think.
It's one thing to recreate a library, I'm not sure how happy the NativeUI author would be if I basically took their internal identity and duplicated it. It wouldn't be hard to do, I'm just not totally convinced on the ethical side of things... maybe that's something to consider if I actually get the whole thing finished.
@LeeC2202 Yeah I'm not saying you should do it, I'm just saying it might be possible that way.
@Jitnaught I genuinely believe that if you are suggesting it, then it may very well be possible. I have every reason to believe and respect the people that are what I class as the "genuine programmers" on this forum and you fit right in there.
If my comment seemed a bit abrupt, you'll have to forgive me... I want to get something done today but I have a mighty migraine that is trying to dictate otherwise. As if I didn't already have enough problems trying to write this... damned head. Every minute with a headache is a minute I can't be productive and every minute counts when you work as slowly as I do.
Aw thanks, that's awesome of you to say.
Yeah it sucks when you want to work but just can't. Also I think it's perfectly fine that you work slowly; quality over quantity!
It's funny how tripping over something in your own code can make you discover bugs in something else.
One of the things I have decided to do differently to NativeUI, is moving more menu processing into a more dedicated MenuManager class, so all showing and hiding menus, switching menus etc... is handled there through various events. That means that instead of checking to see which menu is visible and processing that (or them), as NativeUI does, it has an active menu and only that menu will get processed.
It was after doing this that it got me thinking... because NativeUI says to set a key to make a menu visible or not and that key only applies to one menu, what happens with nested menus when you are several levels down and you press that key. Sure enough, go two levels down, press the activation key and the level one menu suddenly appears again in the background... as well as the menu that is already on screen. That actually manages to take 115fps down to 42fps, which is a remarkable, yet completely undesirable achievement.
It also probably means that you could theoretically take that second instance of the main menu down a level and then create another instance of the main menu, resulting in three separate menus on screen, all being processed.
I am now thinking that maybe this project needs splitting from this thread into a [WIP] topic, as it is probably about as big a derailment as could ever possibly exist. So I think I need to call in the site Overlord.
@rappo is it possible to fork this thread into its own entity from this comment https://forums.gta5-mods.com/topic/6251/script-rewrite-benny-s-motorworks-sp-mod-into-a-asi-performence-increased-script/38
... (with that comment being the first comment in the new thread) and to leave it in a state where I retain control over things like the thread title etc?
@LeeC2202 Forked! Feel free to change the topic name
@rappo Thank you.
So today is one of those self-doubt days I tend to have, fueled by obvious mistakes that I fail to see first time round. What happens in those instances is I end up writing workarounds and the more workarounds I add, the more I doubt my ability... as it turned out, I spotted the mistake and dealt with it properly.
So the current status is that multi-menus are now working fine, as you can see in this video. Rather than go with a parent-child system, I have opted for a MenuStack in the menu manager. The biggest benefit of that, is the ability to branch menus from absolutely any point in the stack and them require little management to do so. Adding or removing menus from the stack creates a natural linear process that handles itself... so I think that was a sensible design choice.
You can also see that it is quite happy to draw menus with or without the scrollbar, as the first two have one and the third menu doesn't. The menu activation key only functions when there are no menus on screen, so that avoids any risk of menu duplication... although the fact that there can only be one active menu at a time pretty much deals with that anyway.
What did occur to me, is that I am trying to replicate a system that I don't understand fully. Because I don't run menu based script mods (or any script mods come to that, beyond my own), I have no real idea how people are creating and using menus. I keep thinking about the problems of adding mouse support, with no real idea of how many people are interacting with mod menus using the mouse.
I have to be careful I don't allow my design philosophy create a system that doesn't cater for what everyone needs but I equally have to be careful I don't try to mimic a design philosophy that nobody really uses. My gut instinct is that up/down/left/right menu systems are better suited to an up/down/left/right input method. The Rockstar menus don't want you to click on tiny arrows to change values, at the very most they want you to click to the left or right of the display text... but do people want to click text at all to change that value, or simply press a left/right key?
I think all I can do is try and utilise what I know and try and create a menu system that is functional, stable, light on resource usage and doesn't get bogged down by trying to be more than it needs to be.
@LeeC2202 Wow nice man! Mouse using feature reminds me of the old MTA Sever days But keep it as optional option. It could be very useful to illustrate something like a own menu that looks like a computer screen if you know what i mean. Something like a ATM
Well it's been a fairly slow night on the whole but I think I now have the system reporting all menu state changes back out to the calling mod through the required events, OnMenuChanged, OnMenuClosed, that kind of thing. Also added the code required to allow certain game controls to function while the menus are active.... I have to confess, NativeUI provided a nice list of relevant controls that proved to be a massive help on that score.
Other than that, some colour setting code for the subtitle colour, a couple more constructors that expose some more of those settings and a few bits of property access code have all been added. One of those days where I feel as though I have typed a lot but there's not a massive amount to show for it from the outside.
What this means now though, is that I have something that I can put into a real mod scenario. I have all the functionality there that will allow me to move my Auto-Snap mod over to this system. I think a fully functional test is exactly what I need, to make sure things don't fall over outside a simple test-bed. It takes me away from working on this directly for a day bit it will be time well spent in the long run.
So as planned, today I ported my Auto-Snap mod over to use my new menu system. A few tweaks were required to the library to make it a bit easier to move things over, probably took about 10 minutes to convert the mod when all the library tweaks were done.
I think the end results speak for themselves. In its current state, my new library is just 28Kb, about a third of the size of NativeUI at this point in time.
And just in case anyone thinks it's just a placed camera with a non-functional menu overlaid, here's a video.
this so awesome! Great job! Convert more for it :D
The difference is so much clear. And you have my dream FPS number in the game! I only have a 980Ti. I still wait for the 1080Ti
So the final act of the day was to implement the other custom control I had intended to add, that's the MenuImageList control. The video probably shows better what this item does, although the name is fairly obvious.
As you can see from the video, the image will always appear aligned with the top of the associated menu item.
I know I can think of things this will be useful for, not least something like a vehicle spawner or ped spawner where you can add images to be displayed on the menu.
The way this works, is you create a folder in your scripts folder and that contains the images. You create the item with something like this
VMenuImageListItem myImageListItem = new VMenuImageListItem("Car List", itemlist, "Cars", ".jpg");
The parameters being the text displayed on the menu, the list of items, the name of the folder containing the images and the file extension of the images.
The name of the images must match the names of the items in the list, so in my list it might say "Ford" and there must be a matching ford.jpg in the Cars folder. That's easy to ensure though, as you simply build the list items from the filenames in that folder before you create the menu item instance.
So with that, I think all potential menu items are now added and it's time to concentrate on more of the inner workings. That means that very little will change from the appearance side of things, unless I make modifications to how the menu items are actually drawn in the menu.
I do keep considering the sprites that NativeUI used for the arrows and check boxes but sprites mean requesting texture dictionaries and that introduces the potential for delays. This needs to be light and fast, so I think I will sacrifice cosmetics at that level, for functionality and speed.
@LeeC2202 First up, this new feature looks very elegant already.
About sprites in your menu, True that, calling sprites will eat more resources than one without. And this may hamper the initial reason of this creation.
I too had created a custom menu back for Uber ride, but man that looked ugly as hell. Thus I had to drop it and stick with native UI. (:
Anyways, overall, a very good progress so far.
oh and BTW, congratulations on being promoted as moderator, we have a really smart moderators team now.
@ashishcw I don't think I would class it as promotion, it's just one more ball to juggle. Maybe I'll last longer as one this time, than I did the previous two times.
The downside is that all those questions that can't get asked on the forums, like console modding etc... get asked directly via PM instead... oh the joy.
Minor cosmetic changes underway at the moment and an additional piece of functionality with the IncDec item.
Cosmetic wise, I am simply removing the arrows when an item isn't selected. I also need to look into the drawtexture function for the ImageListItem to add some aspect ratio compensation code. Images are looking a bit stretched/squashed, so I have to compensate for that. Bit tricky because I play on 16:10 monitors, so I don't know how things look at 16:9 resolutions. Even if I set the game to 1920x1080, my monitors will still stretch the image to 16:10.
Functionality wise, it's just the addition of a CanWrap bool to the IncDec item to allow it to wrap around at the minimum and maximum values.
Edit: I am also thinking about adding an option for each menu to be able to turn the hud off while it is displayed but I'm not sure if that should be a function of the menu manager or each individual menu. I might try it in the menu manager first.
@LeeC2202 perhaps if you use windowed borderless mode you can test on different aspect ratios. It seems to work right on my 21:9 screen in 1920x1080.