We’re trying to supplement the “Utilities” → “Map” Blueprint library with two additional functions:
An Invert function, which swaps the keys and values of a map (assuming the values are unique).
A Build function that can assemble a map from two arrays of equal length – one containing keys and one containing values.
For reference, here’s the code for what I’m describing below:
For the “Invert” function: we followed the patterns in UBlueprintMapLibrary ( Engine\Source\Runtime\Engine\Classes\Kismet\BlueprintMapLibrary.h ) but since our function needs to both take in a map and return a map there doesn’t seem to be any way to properly define the type of the result in relation to the original types (i.e. we need to be able to say that a map with keys of type X and values of type Y becomes a map with keys of type Y and values of type X).
In addition, it looks like the engine uses the MapParam annotation on the UFUNCTION() to perform some “magic” under the hood to transform the integer parameters into wildcard map parameters, but there can only be one parameter that is targeted by this annotation, even though code elsewhere says that the parameter is pipe-delimited. It looks like this is caused by an assumption in FCastWildCard::FCastWildCard() because there’s a comment that reads Map container param types (only one param per function call) above the code that parses the map parameter when wiring up the wildcard. So it doesn’t seem like there’s a way for a map-related blueprint library function to handle any more than a single map at a time.
For the “Build” function: I figured that this might be more straightforward since it’s like the Map_Keys and Map_ValuesUFUNCTIONs, but in reverse. I even got Blueprint to accept and display what seemed like the right types. But when the Blueprint gets compiled, the whole Blueprint graph gets filled with errors and suddenly the function refuses to accept the types it previously accepted.
Though it’s true that you can do this in Blueprint using the approach you described, I was trying to find a generic way to do it that didn’t involve instantiating so many nodes. It wasn’t possible to do it with a macro nor a Blueprint function because it would be coupled to the specific key and value type of the map.
After a lot of research and trial and error, I eventually was able to build a solution to creating a custom “Invert” node that works with any map if it has a value type that can be used as a key type. The implementation is complicated because it required both a custom K2Node and a custom thunk so that the input and output pins are type safe.