Jump to content

Part Metadata + Drawing Part Icons


Recommended Posts

Hello there,

After some fiddling around with the AvailablePart, PartLoader and EditorPartList classes I've come to no real conclusion on this one.

I already had this in the help a dev thread but as it's a bit scattered apart and a few new things popped up, so I thought to maybe give it it's own thread.

I'm currently working on a plugin that allows you to dynamically tag parts in the editor in order to put them in custom categories and filter them based on these tags. This already works pretty well so far, the basic framework and featureset is worked out but in order to get this to the volume I want it to provide I still have to iron out a few things.

There are two big ones which I'd like to address first as well as a smaller one which could work around even it doesn't work out really.

1) Part Paths

I'm trying to find the actual URL / path of all available parts. This would be needed in order to get the mod folder in GameData the part cfg resides in in order to allow for automatic mod tagging (You add a new mod and are able to generate a preset category instead of having to haul all new parts into a group manually).

Sadly the API is very obscure on this point.

I first tried to use the PartLoader.LoadedPartList which provides a list of AvailableParts. Sadly for these no fields apart from the actual AvailablePart.name are set so I tried using the PartLoader.getPartInfoByName method as I thought those additional fields might be filled only when explicitly asked for some reason, didn't work out aswell. I should add the ConfigNodes on those were empty aswell.

I then tried to get some properly filled AvailableParts via the EditorPartList.Instance.limitedParts but that List wasn't filled in any occasion at all even when all parts where displayed or filtered out.

2) Part Icons

For the actual Tag management I'm using a simple list of part names at the moment. For the finished version I'd prefer to the 3D model of the part just like the editor does. I found no obvious way to do that looking through the class definitions. Incase this doesn't work out this one is still somewhat dependant on 1) as I'd need proper part titles for the list as the part names are pretty hideous looking on their own.

3) Button Icons

The categories / Tags are displayed along the top of your screen as a continuation of the default categories button list, each tag can be given a custom icon but I'm currently looking into a way to draw the default part icon for staging on a button (just to provide some default icons for custom tag groups without properly set up icons). So is there some way to get the actual Texture2D for the default buttons instead of just that DefaultIcons enumeration? This is a minor one as it could just be worked out with some assets for some default button textures.

If someone got an idea, a solution for those problems or even a mod that does something similiar to said problems to have a look at, I'd be very grateful if you'd throw me a bone.

Link to comment
Share on other sites

I've determined that only partURL and typeDescription are null in the PartLoader.LoadedPartList instance. All the other fields are there (though the filePath property also returns null.) Trying to figure out how to get the url or path; it should be possible because how does the engine instance a Part from the AvailableParts list?

Link to comment
Share on other sites

You can grab the Part from an AvailablePart using the partPrefab field e.g. PartLoader.LoadedPartList[3].partPrefab. From there you can use the Modules property of Part to get a list of PartModules attached to the part. The problem with trying to sort by mod is that some mods simply attach PartModules to existing stock parts, so there's no way necessarily to distinguish between stock and mod parts. You could construct a file system graph (make sure you use System.IO without a using directive -- it messes with Unity functions; you'll have to fully qualify the System.IO methods) then compare the PartModule.moduleName to the names of each of the folders to determine which parts sit in the Squad folder and which don't. (You can use KSPUtil.ApplicationRootPath to get the root directory.)

Link to comment
Share on other sites

Ah nice the PartModules one is an interesting option for further sorting parts.

All assemblies referencing System.IO won't be loaded by KSP as disk access is sandboxed via KSP.IO. If that would work I'd just parse the part.cfgs for names myself but like this - no luck.

Link to comment
Share on other sites

Your project sounds like a superset of what I'm working on: a simple sort and filter mechanism for the part list. I got the sort working and just have GUI coding for the filter capability, but I think I'll abandon the project to wait for your more polished-sounding offering. I was just using the idea as a way to get my feet wet in the plug-in world anyway.

Link to comment
Share on other sites

All assemblies referencing System.IO won't be loaded by KSP as disk access is sandboxed via KSP.IO. If that would work I'd just parse the part.cfgs for names myself but like this - no luck.

Ah. I wondered about that. You could (yes it's ugly) pre-generate a file graph in the ConfigNode xml format, then serialize from it using the ConfigNode interface.

has the outlines of how it might be possible to do this.
Link to comment
Share on other sites

Here's the code you're looking for:

string findPartMod(AvailablePart part)
{
string mod = "";
UrlDir.UrlConfig[] configs = GameDatabase.Instance.GetConfigs("PART");
UrlDir.UrlConfig config = Array.Find<UrlDir.UrlConfig>(configs, (c => part.name == c.name));
if (config != null)
{
var id = new UrlDir.UrlIdentifier(config.url);
mod = id[0];
}

return mod;
}

It grabs the list of PART type configs from GameDatabase, then searches for a name match, then parses the url for the root namespace. I'm not sure if this is the best or most efficient way to do this (suggestions welcome) but it works. This should work for all mods, except that some of them have a manufacturer ID in the root namespace instead of the mod name. There's no standard way to traverse the url for mod name except to grab the root though. If you want to filter stock only, just compare the return value of this method to "Squad" like so:

EditorPartListFilter filter = new EditorPartListFilter("Stock Only",
(part => findPartMod(part) == "Squad"));
EditorPartList.Instance.ExcludeFilters.AddFilter(filter);
EditorPartList.Instance.Refresh();

Edited by Mr Shifty
Link to comment
Share on other sites

FYI, part names in urls have '_' instead of '.' in the name. Here's an improved version of findPartMod:

string findPartMod(AvailablePart part)
{
string mod = "";
UrlDir.UrlConfig config = Array.Find<UrlDir.UrlConfig>(configs, (c => part.name == c.name.Replace('_', '.')));
if (config != null)
{
var id = new UrlDir.UrlIdentifier(config.url);
mod = id[0];
}

return mod;
}

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
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...