Jump to content
LaunchBox Community Forums

My Wishlist Of Plugin Focused LaunchBox Features


Recommended Posts

@Jason Carr Expanding on our conversation the other night in the thread about difference's in the plugin Engine Between OG LaunchBox and LB.Next, I would like to take this opportunity to list some of the minor changes I talked about, and had previously used hacks (such as reflection) to partially achieve.

I am going to forward this list by saying I am in no means expecting any of these features to be implemented quickly (If half of these get implemented this year I will be very happy), and I think I speak for the whole LB Community by saying that everyone really appreciates the work that you do, and the fantastic job you have done with the new version of LaunchBox (LB.Next). If you disagree with any of these ideas feel free to completely veto them as you are, after all, the developer of LaunchBox, though if that is the case I would at least like a reason. There are only really two things on here that may potentially prevent me from making an awesome version of my current plugin, the rest are things I have thought would be nice in the past, and would make use of if available but are by no means absolute show stoppers. The list is ordered in terms of priority from my perspective of creating my current plugin, and I will use that as an example to why I would find these features useful. Also a fair warning to anyone else reading this the below list is quite technical.

  1. Access the game being started from the "GameStarting" event
    Don't know what the best way to expose this, in terms of the plugin Api would be, but this feature would help me out loads. For my plugin to work seamlessly (i.e. as little manual user setup as possible), it is going to need to make a GET Request to check if a config is present and pull down some data if it is, on a per-game basis. I initially thought about looping through all the games while LaunchBox starts, but the problem with this is that it's going to take time (especially if the user has a large PS2 Game Collection). So I eventually settled on the idea of doing this step when the user actually plays the game (There were various less than perfect work-around's to achieve this in OG LaunchBox). There is already the "GameStarting" event in the LaunchBox plugin Api, which in theory allows the plugin to execute logic before the game actually starts, the problem is we have no access to what game is actually starting so we cannot currently put game specific logic in here. Another less than ideal option for this that I had thought of was to launch an additional application to execute such logic (see Number 6), but that seems like jumping through more hoops than necessary and introduces additional problems. An on "SelectionChange" event (combined with knowing the selected game) would also be very welcome here, as a replacement for what used to be possible from the GetIsValidForGame Method.
  2. Retain Launcher tab strings (like Configuration Path), Even when emulation is on
    I mentioned this one the other night, though I understand this one is VERY specific to my own use case, I doubt it'd be particularly hard to implement either. Again There was a less than ideal solution to sort of simulate this in OG LaunchBox because of when the GetIsValidForGame method of a GameMenuItemPlugin was executed (Which was whenever the game selection changed, so these values could pretty much always be set if not already, before it became a problem). But this is not the behaviour I would like to see implemented as this is very much a less than perfect hack for something that should be relatively simple. If ConfigurationPath or ConfigurationCommandLine parameter is already set (Either in the XML file or by a plugin), I see no good reason why that shouldn't be retained when saving from LB's Edit Game Dialog, even with the setting to "Use an emulator..." enabled. The logic to make the button work is all already there and works perfectly, The field's could still very much be read-only and not editable from the frontend, so not to confuse the user. In my case it makes a lot of sense to use the built-in "Configure" option as a shortcut to open PCSX2 with the created Game Config for the given game.
    1. [The Suggestions below are really all just nice to have's and not super important for my current plugin]
  3. Option to Hide GameMenuItemPlugin completely if it is not valid for the game
    This one simply just annoys me as it seems so simple on the surface, this was the first plugin related problem I encountered that I turned to reflection to try and solve, I even made a thread about it at the time, which explains roughly how I achieved it. Picture this scenario a user has maybe 10-20 plugins installed, most of them only work on a rather small subset of games, they are going through their SNES library but for some reason still have a greyed out option for PCSX2 Configurator, I just don't see the point in this. I guess you could argue that it keeps the context menu consistent between games (which I'm guessing is part of the reason why it's the case for the rest of the menu), but I really don't feel that matters too much for things under the final (plugin) separator. I would understand if you wanted to leave in the option to disable (grey out) the plugin, but I really feel there should also be an option to hide it.
  4. Allow custom fly-out menu (and possibly more customisation's) for GameMenuItemPlugin
    This one might involve a reasonable amount of effort to implement and I can fully understand why it is not like this, this was one of the few thing's that reflection actually worked reasonably well for in OG LaunchBox, though I have no idea how one would achieve that in LB.Next with it's WPF based interface. But it would be really nice to have a way of customising the actual menu item, and to create custom sub-menu's with there own actions and options (Similar to "Image Group" and "Launch With") as opposed to pretty much always having to open a separate window to present a multitude of options, though a separate window does have some advantages from a visual/artistic perspective. In OG LaunchBox I would have suggested just exposing the underlying ToolStripMenuItem from Windows Form's and letting the user play with it as they wished (which could potentially solve Number 3 as well though not entirely sure on that), but I am still new to WPF and don't know what the equivalent control would be, or if it can be used in that way.
  5. Provide option to hide a custom field from the UI and provide nicer implementation
    This is a small issue, especially with the current build of LaunchBox.Next where custom fields are barely in the UI anyway (don't know if that is due to change in the future). But it would be really good to be able to use LB's built in custom fields for per-game plugin settings, and in that case you probably wouldn't want the user to be able to sort by "PCSX2Configurator_CheckForConfigUpdatesOnStartup". The ability to hide the field could be combined with a dictionary based implementation through the current plugin engine (as opposed to a basic collection like it is now), for a really killer and easy to use system.  An alternative solution to this would be a separate system just for use by plugins, though honestly I'm not sure if that's really worth it as it's not super hard to roll your own for this, just a very nice feature that is essentially already there but awkward to utilise for that purpose currently.
  6. Provide an option to hide an Additional Application from the Context Menu
    This is quite a minor gripe, though would also be incredibly easy to implement, and if used in a smart way could have a reasonably positive impact on the user's experience. It is sort of similar conceptually to Number 1, but with the idea that the plugin could launch an external application before the game started (which LB already allows natively). If a script or action was to be executed in this way, then it's probably more of a utility and not something the user wants to see every time they right click on their game, and if it is placed there by the plugin itself as a means to an end then it is definitely not something the user should be able to easily click on, though that second use case would be pretty much completely redundant if Number 1 was implemented and at that point this one isn't really related to plugins, but just another option for the user. 

A big thank you for reading this mega long post (sorry about that), and hope that gives you an insight into some of the issue's I've been having with LB plugin development (some pretty much since the plugin engine was first launched) and my general mindset when creating plugins for LaunchBox, and why the features above are on this list. I just want to say thank you again for such an awesome piece of software with such a versatile plugin engine that really allows me to essentially create the perfect emulator frontend (Which was always my dream since I was like 12, also LB itself is pretty close to the mark). It's a shame I don't actually get that much time to use LaunchBox itself nowadays but it is still an incredibly awesome piece of software, and I have really enjoyed my time so far developing plugins for it, and hope to eventually have a definitive version of my PCSX2 plugins and develop more awesome plugins for LaunchBox. If anyone else (other than Jason) has any insights on any of the things said in this post, or faces similar issues with plugin development, please feel free to chime in.

 

Edited by alec100_94
  • Like 1
Link to comment
Share on other sites

Im not to great with the technical stuff but im assuming your number 1 request is the same question i asked in the themes/xml help thread recently.

 

Jason replied with something like. Use the onSelected method to store private variable to access with the gamestarting event. 

 

I was sort of on the right track with that one but not quite. You'll see my noob code skill in that thread also. 

 

Unless iv miss understood your request which is highly likely. 

Link to comment
Share on other sites

@jayjay You are along the right lines, but I fail to see how that actually achieves what I am trying to do. I want a surefire way of knowing what game is starting whenever any game is starting (and the "GameStarting" Event is fired), regardless of what was called before it or how the game was started. If a user open's LaunchBox and double clicks on a game, I want to know which game that was in the "GameStarting" event. As far as I'm aware the OnSelected Methods only trigger when the GameMenuItemPlugin is selected from the games context menu, and only returns the game that it was selected from. This would mean to get the selected game the user would need to click on my plugin from that games context menu first, and if a user then went to select another game the value would be wrong. This kind of defeats the point of the automation I am trying to create here, as if the user is clicking on the plugin anyway, we may as well do the logic there instead of when the game starts. Don't get me wrong, It's not impossible that I'm wrong, and if you think you have working code that does actually achieve what I describe then I would love to see it.

Also after rethinking about the priority of the request's in the above list, I think Number 2 (Retaining ConfigPath Values) is actually more important to me at the moment, as I can easily release a version of my plugin without the automation, but having the ConfigPath being potentially cleared is always going to create a minor bug.

Edited by alec100_94
Link to comment
Share on other sites

You no doubt know more than I do. Im a c# noob as well as a LB api noob. With jasons advice Iv been trying, when I can, for a couple of days now to get game info on gamestarting event without success, as you say it seems the onselected methods are just for game/menu items. 

 

Im trying to get image/video paths etc for any game that is launched with the "Play" and "Launch With" options in the game menu. Avoiding the need for the user to select my plugin from the game menu. 

 

Maybe jason misunderstood my non technical mumbo jumbo, that or im to dumb to work it out. Anyway I apologise, I have no code to share that works. 

Link to comment
Share on other sites

@jayjay don't sweat it, everyone has to start somewhere. I'm reasonably sure I know what I'm talking about here as I've been using this Api pretty much from the day it was released, have been coding for around 8 years, work as a full time web developer (mostly C#), and have a degree in Games Technology (Not really trying to show off, or anything). I'm guessing @Jason Carr probably did just misunderstand what you meant, maybe he can shed some light on this?

Though if this is the feature you actually need, then you can probably see my frustration with it not being there. Just out of interest what is your overall goal? I might be able to help.

Edited by alec100_94
Link to comment
Share on other sites

Heres our thread:

https://forums.launchbox-app.com/topic/46069-pause-menu/

 

Heres a vid of where we at so far:

https://www.youtube.com/watch?v=3FGAz2J0TuU&feature=youtu.be

 

We are using autohotkey because its simple and a lot less frustrating, I struggle finding the time to learn c#. By the way im a ground worker. I move heavy stuff, concrete floors, cement blocks, basically grunt work. Coding doesn't come natural to me, I guess its just a hobby.

 

Im not expecting you to be able to help with anything as im not sure there's much needs doing and also if your capable of bringing yourself down to my level haha. Heres the plugin iv manage to scrape together so far:

namespace ClassLibrary2
{
    
    public class Class1 : IGameMenuItemPlugin
    {      

        public bool SupportsMultipleGames => false;

        public string Caption
        {
            get
            {
                return "Launch With PM";
            }
        }

        public System.Drawing.Image IconImage   
        {
            get
            {
                return null;
            }
        }

        public bool ShowInLaunchBox => true;

        public bool ShowInBigBox => true;

        public bool GetIsValidForGame(IGame selectedGame)
        { 
            string retroarch = "retroarch.exe";

            foreach (var emu in PluginHelper.DataManager.GetAllEmulators())
            {
                var emuid = PluginHelper.DataManager.GetEmulatorById(emu.Id);

                string emuapp = emu.ApplicationPath;
                string someBS = emuid.ToString();

                if (emuapp.Contains(retroarch))
                {
                    Emulator = "RetroArch";
                    if (selectedGame.Platform == someBS)
                    {
                        return true;
                    }
                }
            }
            if (retroarch == "returnthisyouprick")
            {
                
                return true;
            }
            else
            {
                return false;
            }
        }      

        public bool GetIsValidForGames(IGame[] selectedGames)
        {
            return false;
        }

        public void OnSelected(IGame selectedGame)  
        {
            var emulatorID = PluginHelper.DataManager.GetEmulatorById(selectedGame.EmulatorId);
            var emuPath = emulatorID.ApplicationPath;
            string emuFileName = Path.GetFileName(emuPath);

            string PmPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PauseMenu", "Scripts", Emulator + "-" + selectedGame.Platform + ".exe");
            string PMArg = AppDomain.CurrentDomain.BaseDirectory + "|" + emuFileName + "|" + selectedGame.Platform +"|" + selectedGame.GetVideoPath() + "|" + selectedGame.FrontImagePath + "|" + selectedGame.BackgroundImagePath + "|" + selectedGame.BackImagePath + "|" + selectedGame.Box3DImagePath + "|" + selectedGame.Cart3DImagePath + "|" + selectedGame.CartBackImagePath + "|" + selectedGame.CartFrontImagePath + "|" + selectedGame.ClearLogoImagePath + "|" + selectedGame.GetMusicPath() + "|" + selectedGame.ScreenshotImagePath;
            
            Process PM = new Process();
            PM.StartInfo.FileName = PmPath;
            PM.StartInfo.Arguments = PMArg;
            PM.Start();
        }

        public void OnSelected(IGame[] selectedGames)
        {
            return;
        }
    }
}

The valid for method...  I want it to be valid for certain emulators, in this case retroarch. I haven't spent much time on this but reasons unknown to me, somehow this seems to work. In my mind this makes no sense.

 

But @Axenn did suggest this:

var emulators = PluginHelper.DataManager.GetAllEmulators();

// it's an array you could access by the row, example:
emulators[0].ApplicationPath;

Which is obviously a little more elegant than my mess haha. I just haven't got round to it yet.

 

As you can see in the onSelected method this plugin will launch "Emulator filename-Platform.exe". I was thinking of creating multiple scripts based on platform but that creates a mess if I wanted to update stuff. I haven't figured out exactly what to do just yet.

 

The onSelected will also send image/video paths etc as arguments as autohotkey can capture these. I can then give the user the option of displaying  front-cover, per game video etc etc within the menu. But at the moment this will only work as a gamemenuitem using play() which means It wont open if the user chooses "launch with" etc.

 

As you can see from my terrible code I am a proper noob. I didnt read any tutorials or learn anything c# before jumping in to LB api and using google. I know this is naughty, I could tell how naughty from how many down votes Iv got on stackoverflow since iv started c# haha.

 

Anyways as I said I dont think theres much to say, but thought I would share what we are up to. 

 

Link to comment
Share on other sites

Ok well, There is definitely a better way of doing that lol, Also AHK is actually a really good choice with LB if used properly (though I kind of despise the syntax). to check if the game is using retroarch you really only need something like this. I have shortened it to one line for easiness, it may be neater to split it up if this confuses you.

public bool GetIsValidForGame(IGame selectedGame)
{
    return PluginHelper.DataManager.GetEmulatorById(selectedGame.EmulatorId).Title.ToLower().Contains("retroarch");
}

The rest of it doesn't look too bad on the surface. I don't know if it'll help you but I open-source all the LaunchBox stuff I do, so here is the github repo for the new version of my PCSX2 plugin I am writing, and here is the old version (which is pretty much over complicated and broken in places), and here's a link to an even older version of my plugin that was more stable and less complicated (even uses an AHK script for a lot of the logic). Hope that helps.

Edited by alec100_94
  • Like 1
Link to comment
Share on other sites

Lol. Ok. Thats slightly better than my work. And thanks for git link, iv been using others examples as well. 

 

Check this out.

Untitled.thumb.png.693a6b01d34435fc60f2685dbf63c110.pngUntitled2.thumb.png.fc826200ebe6534061b5d9e6a96d5726.pngThis is retroarch save states as gamemenuitem. It even uses wpf... yeah.

Now picture if you will... based off my plugin above... the code behind this lol. And no Im not showing you or anyone haha.

Link to comment
Share on other sites

Hey @alec100_94. Would you mind helping me out with something please.

public class Class1 : IGameMenuItemPlugin, ISystemEventsPlugin
    {
        

        IGame[] _filteredList;

        public string SelectedGamePlatform { get; private set; }

        public bool SupportsMultipleGames => false;

        public string Caption => "testing";

        public Image IconImage => null;

        public bool ShowInLaunchBox => true;

        public bool ShowInBigBox => false;

        public bool GetIsValidForGame(IGame selectedGame)
        {
            return true;
        }

        public bool GetIsValidForGames(IGame[] selectedGames)
        {
            return false;
        }

        public void OnSelected(IGame selectedGame)
        {
            SelectedGamePlatform = selectedGame.Platform;
            
            IGame[] _allGames = PluginHelper.DataManager.GetAllGames();
            IGame[] _filteredList = Array.FindAll(_allGames, GameCheck);
            
            _filteredList[0].Play();
        }

        public void OnSelected(IGame[] selectedGames)
        {
            return;
        }       

        private bool GameCheck(IGame g)
        {
            if (g.Platform == SelectedGamePlatform)
            {
                if (!File.Exists(g.GetVideoPath()))
                {
                    if (g.Broken == false)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        public void OnEventRaised(string eventType)
        {
            if (eventType == "GameExited")
            {
                _filteredList[1].Play();
            }
        }
    }

How would I access the _filteredList[] from the OnEventRaised. Everything iv tried results in nothing happening.

I want to be able to exit a game and have the next game that is missing a video launch on the previous games gameExited event.

Hope you dont mind me bothering you with this.

Link to comment
Share on other sites

@jayjay I sent you a PM trying to describe how to achieve what your doing.

@Jason Carr Also realised I am being rather dumb with at least one thing, today I found the PluginHelper.StateManager.GetAllSelectedGames() which I had somehow glossed over before, though for some unbeknown reason that function seems to be returning null when a game is selected (I'm guessing it used to work in OG LB?), so if that can be re-implemented that issue is essentially solved.

However on rethinking (again) the main thing I really want to see (in addition to that), is the introduction of an OnSelectionChange Event which was also essentially possible in OG LB through the GetIsValidForGame. These two things are really all I would absolutely need to ship a feature complete version of my plugin (though retaining the config path would still be a nice thing to have, if not really essential if I can add the values on selecting the game).

Edited by alec100_94
  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
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...