Hello,
I am trying to keep strong typing in C++ while still having a usable DataAsset workflow in the editor.
I have a simple goal:
I want a TMap that uses a strongly typed FName to behave exactly like a normal TMap<FName, FName> in the Details panel.
Right now these two properties behave very differently in the editor:
TMap<FName, FName> → nice inline editable key field (works perfectly)
TMap<FGameIdDialogueScene, FName> → nested struct UI that makes authoring the map extremely painful when it grows :
Here is the code:
UCLASS(BlueprintType)
class MYGAME_API UTMapTestDataAsset : public UDataAsset
{
GENERATED_BODY()
public:
UPROPERTY(EditDefaultsOnly)
TMap<FGameIdDialogueScene, FName> mMapWithFGameIdDialogueSceneAsKey{};
UPROPERTY(EditDefaultsOnly)
TMap<FName, FName> mMapWithFNameAsKey{};
};
USTRUCT(BlueprintType)
struct MYGAME_API FGameIdDialogueScene
{
GENERATED_BODY()
public:
FGameIdDialogueScene() = default;
explicit FGameIdDialogueScene(const FName InValue) : mValue(InValue) {}
bool IsValid() const { return mValue != NAME_None; }
friend bool operator==(const FGameIdDialogueScene& A, const FGameIdDialogueScene& B)
{
return A.mValue == B.mValue;
}
friend uint32 GetTypeHash(const FGameIdDialogueScene& Id)
{
return GetTypeHash(Id.mValue);
}
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FName mValue{ NAME_None };
static const FGameIdDialogueScene None;
};
For now the only workaround I found is to use a DataTable and use the row name as the value to initialize my ID type. It technically preserves the strong typing in C++, but it forces me to maintain a DataTable and parse it every time, which makes the workflow quite painful and significantly complicates my data structures but its easier to read… So it really feels like a very hacky solution rather than a proper one…
I know that in theory this should be solvable using a Details / Property customization.
The problem is that I already tried to implement one and spent about two full days on it, and I never managed to get a reliable result for a TMap key. Sometimes the text just disappear, sometime the TMap is not even visible…
So at this point I’m not sure whether:
-
I misunderstood how the property system is supposed to be extended
-
or whether TMap keys based on a USTRUCT wrapping an FName simply cannot be made to behave like a native FNameProperty
What I’d really like to know is:
- Has anyone actually succeeded in making a USTRUCT that wraps an FName display exactly like an FName when used as a TMap key in the Details panel?
And if it is possible:
- Is this something that must be implemented separately for each struct type, or is there a generic way to support multiple “strong ID” types (for example several FGameId-like structs) so they all render as a single FName field?
Basically I’m completely open to the idea that I did it wrong, but after two days of attempts I need to know if I’m missing a specific hook, or if the engine just doesn’t support this use case and the behavior I’m seeing is expected.
Thanks for any guidance.
