Log in to reply
 

Help With LemonUI Menu



  • I love LemonUI but the documentation is seriously lacking and help on the Lemon discord server (my opinion only) is as useless as tits on a nun. For the benefit of those non native english speakers not familiar with this colourful idiom, nuns don't need to have tits. A similar expression is tits on a bull, because once more a bull, unlike a cow, does not need tits.

    For professional programmers this isn't an issue. They can figure anything out. But for a talentless non-programmer hack like myself, it leaves me frustrated and in danger of doing serious damage to my PC.

    So if anyone can help, realizing that very few professional programmers lurk around here, this is what i'd like to do.

    I'd like first to return all the files in a specific directory (fixed) with their extensions.
    The directory would be scripts/music and the files would all be mp3. For example, mysong.mp3.
    If i did this from a batch command, I could get a list like this:
    DIR /b c:\testFolder

    So I"d like to get all those mp3 files and then have them displayed as menu selections in my LemonUI menu.
    I already have the code to play mp3s with NAudio.dll, so this would allow me to play my songs in game, as opposed to just in the car.

    Ok, so even an idiot like myself could hardcode the songs into a menu. But I want this done at runtime because i"ll constantly be refreshing the files in the music folder. Likely a dozen files max at any time. The menu items will reflect the current contents as the game loads and the menu is refreshed.

    There is a mod that does exactly this, but it is overkill. I don't need volume controls etc. They creator made sure the code could not be reverse engineered. Not sure how he did it, some form of encryption I guess, but it is pure gibberish when decompiled. The mod in question is called Free Music.

    IMPORTANT: Not trying to ripoff this mod. I just wanted to see his code for my own personal use. Most importantly I could learn lots about arrays, and reading from the system, and looping through to add each item to the menu. Not creating any mods for distribution.



  • This post is deleted!


  • @JohnFromGWN

    Then, you can use the Directory.GetFiles(path string, string searchPattern) function to get all files whose extension matches the search pattern, so that you have the complete path to the files you want.

    Having the file paths handy, I guess you will want to show only the name of the song in the menu, right? To do this, just look at the example:

    using GTA;
    
    using GTA.UI;
    
    using System.IO;
    
    using System.Collections.Generic;
    
    
    namespace Helideck_Signaling
    {
        internal class Class2 : Script
        {
            public Class2()
            {
                var pathToTheScriptFolder =
                    GetRelativeFilePath("music");
    
                var pathOfAllTheSongsFoundInTheScriptFolder =
                    Directory
                        .GetFiles(path: pathToTheScriptFolder, 
                                  searchPattern: "*mp3");
    
                var songName =
                    new List<string>();
    
                foreach (var pathSong in pathOfAllTheSongsFoundInTheScriptFolder)
                {
                    songName
                        .Add(pathSong
                                .Remove(startIndex: 0, 
                                        count     : pathToTheScriptFolder.Length + 1).Replace(oldValue: ".mp3", 
                                                                                              newValue: ""));
                }
    
                Notification
                    .Show($"Song name - ~y~{songName[0]}~w~\nPath - ~g~{pathOfAllTheSongsFoundInTheScriptFolder[0]}~w~", true);
            }
        }
    }
    
    
    

    you will get a result like this:
    alt text

    is that what you wanted to know? sorry if it's not.



  • @Niziul Hi. I really appreciate your help, but my message wasn't clear.
    What I would like to do is populate a LemonUI menu but instead of hardcoding all the selections, I want the menu to be generated at run time by going through a folder and returning all the file names (songs) in that folder and making each song a menu selection.

    In LemonUI, this involves 2 steps and a 3rd step would just be the actual function to play the mp3 using NAudio.

    Step 1 example:

    //start of SubMenu 1 for Songs
            private static readonly NativeMenu submenu1 = new NativeMenu("Play Songs", "Song Titles From Folder", "");
            private static readonly NativeItem submenu1_1 = new NativeItem("Song 1.mp3", "");
            private static readonly NativeItem submenu1_2 = new NativeItem("Song 2.mp3", "");
            private static readonly NativeItem submenu1_3 = new NativeItem("Song 3.mp3", "");
    

    Step 2 example:

     // 1. SubMenu for SOngs
                submenu1.MaxItems = 20;
                submenu1.Add(submenu1_1); submenu1_1.Activated += PlaySong1;
                submenu1.Add(submenu1_2); submenu1_2.Activated += PlaySong2;
                submenu1.Add(submenu1_3); submenu1_3.Activated += PlaySong3;
    

    alt text



  • @Niziul I have no idea how the creator of Free Music does it, but he reads your song files, on your hard drive, in a folder called freemusic (subfolder of scripts).

    He then creates a menu with the song titles, allowing you to play your own music and refresh the contents of the freemusic folder any time. I think he also checks for subfolders but that's just an added bonus.



  • @JohnFromGWN One way to do this, is to create a new list of songs every time the menu is opened. For that, you can use the menu's Shown event

    using System;
    using System.Collections.Generic;
    using System.IO;
    
    public class Program
    {
    	string[] getSongs() {
    	 var baseDir = $"{Directory.GetCurrentDirectory()}\\scripts\\music";
         return Directory.GetFiles(path: baseDir, searchPattern: "*mp3", SearchOption.AllDirectories);
    	}
    	
    	public static void Main()
    	{
    		NativeMenu musicMenu = new("MUSIC");
    		
    		musicMenu.Shown += () => {
    			musicMenu.ClearItems(); //Delete all the menu items, if any. I think the name was ClearItems, idk, I forgot.
    			var mySongs = getSongs();
    			
    			foreach (var song in mySongs) {
    				NativeItem songItem = new(Path.GetFileNameWithoutExtension(song));
    				
    				songItem.Activated += () => {
    					playSong();
    				};
    				
    				musicMenu.Add(songItem);
    			}
    		};
    	}
    }
    

    So, every time the menu is opened, the previous list is deleted and a new one is created.



  • @JustDancePC This looks like an excellent starting point. Thank you so much. Actually almost a complete script.

    One question right off the bat. The script I assume considers the scripts folder to be its base directory. If that's the case we still need to tell the script to look at the music subfolder, or will it do that anyway?

    Edit: I guess that's why you have search all directories.

    Nvm, got it.



  • @JohnFromGWN
    In this line inside the "getSongs" function var baseDir = $"{Directory.GetCurrentDirectory()}\\scripts\\music"; the baseDir is the path to a folder called "music" inside the scripts folder, that's the starting point for the search. Directory.GetCurrentDirectory() returns the path to the root GTA V folder.

    In this line Directory.GetFiles(path: baseDir, searchPattern: "*mp3", SearchOption.AllDirectories);, the "SearchOption.AllDirectories" variable will tell the function to do a recursive search, this allows you to include any sub directories you have in the music folder.



  • @JustDancePC yes, that's what I thought. Again thank you so much. Will take my best shot tomorrow at implementing and will share outcome and feedback.



  • @JustDancePC omg. I just realized, lack of sleep or cuz I'm an idiot, that the music line was a path.

    In my covid brain state I read too quickly and superficially and interpreted it as a comment, not a path.

    Mistook forward slashes for backslashes! I mean other way around



  • :laughing:



  • God, I hate myself. I've been trying to figure out how to use LemonUI for a long time, just to do this: alt text

    I'm glad justDance showed up.



  • @Niziul That's a good start. I'm great at creating LemonUI menus, just shitty at programming! Self-taught, one day I'll take a course.



  • @JohnFromGWN unfortunately lemonUI is not for me :(



  • @Niziul why not????



  • @JustDancePC

    Ok, so I can't wait until tomorrow even though im brain dead.
    Making corrections based on intellisense and compiler

    NativeMenu musicMenu = new NativeMenu("MUSIC"); // changed new to new NativeMenu
    musicMenu.Shown += () => {  //error here, Delegate Event Handler does not take 0 arguments.
    musicMenu.Clear(); //changed ClearItems to Clear
    
    

    no idea what arguments it can take



  • @JohnFromGWN said in Help With LemonUI Menu:

    musicMenu.Shown += () => {  //error here, Delegate Event Handler does not take 0 arguments.
    

    when calling an event using lamp expression you must pass the arguments between parentheses

    You can do it two ways:

    musicMenu.Shown += (sender, e) => {  };
    

    or

    musicMenu.Shown += (o, e) => {  };
    


  • @Niziul said in Help With LemonUI Menu:

    musicMenu.Shown += (sender, e) =>

    Perfect!



  • @JohnFromGWN said in Help With LemonUI Menu:

    @Niziul why not????

    is because I want to suffer a little, creating menus from scratch. I've been trying to get through this for a week:alt text
    into the game.



  • @Niziul lol



  • @Niziul Just 2 errors now
    songItem.Activated += (o, e) => { }; // CS0136 A local or parameter named 'o' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter Lemon_Tasks

    musicMenu.Add(songItem); //CS0103 The name 'songItem' does not exist in the current context`

    public static void Main()
    		{
    
    		
    			string[] getSongs()
    			{
    				var baseDir = $"{Directory.GetCurrentDirectory()}\\scripts\\music";
    				return Directory.GetFiles(path: baseDir, searchPattern: "*mp3", SearchOption.AllDirectories);
    			}
    			
    			NativeMenu musicMenu = new NativeMenu("MUSIC");
    			musicMenu.Shown += (o, e) =>
    			{
    
    				musicMenu.Clear();
    				var mySongs = getSongs();
    				foreach (var song in mySongs)
    				{
    					NativeItem songItem = new NativeItem(Path.GetFileNameWithoutExtension(song));
    
    					songItem.Activated += (o, e) => { };        //	playSong();
    				};
    
    				musicMenu.Add(songItem)};
    
    
    
    			}
    


  • @JohnFromGWN

    musicMenu.Shown += (o, e) =>

    songItem.Activated += (o, e) =>

    These can't have the same parameter names. It doesn't matter what they're named. They could be

    songItem.Activated += (blah, fdkslajfh) =>

    if you wanted



  • @JohnFromGWN said in Help With LemonUI Menu:

    musicMenu.Add(songItem); //CS0103 The name 'songItem' does not exist in the current context`

    Move that to within the foreach loop



  • @Jitnaught Thank you! But does this mean these parameters are meaningless??



  • @JohnFromGWN The names of them are meaningless. You can name them whatever you want.


Log in to reply
 

Looks like your connection to GTA5-Mods.com Forums was lost, please wait while we try to reconnect.