Redirect for moving float into struct?

Is there a redirect that would work when a simple float UPROPERTY is moved into a struct?

Old Versoin…

UCLASS(Abstract, EditInlineNew, HideCategories="Internal")
class ABLECORE_API USomeClass : public UObject
{
   GENERATED_BODY()
protected:
   UPROPERTY(EditInstanceOnly, Category = "Timing", meta=(DisplayName = "Start Time"))
   float m_StartTime;
};

New Versoin…

USTRUCT(BlueprintType)
struct ABLECORE_API FRelativeTime
{
   GENERATED_BODY()
public:
   UPROPERTY(BlueprintReadWrite, EditAnywhere)
   float Offset = 0.0f;
};

UCLASS(Abstract, EditInlineNew, HideCategories="Internal")
class ABLECORE_API USomeClass : public UObject
{
   GENERATED_BODY()
protected:
   UPROPERTY(EditInstanceOnly, Category = "Timing", meta=(DisplayName = "Start Time"))
   FRelativeTime m_StartTime;
};

m_StartTime has been changed to now be a struct and the float value is now a member called Offset.

I tried a few different variations of this, but haven’t found the magic combination…

+PropertyRedirects=(OldName="/Script/AbleCore.AblAbilityTask.m_StartTime",NewName="/Script/AbleCore.AblAbilityTask.m_StartTime.Offset")

If not, is there some magic I can do in an overridden version of Serialize where I could catch this myself?

Thanks,
-Randy

So I ended up solving this without redirects at all. Through debugging serialization, I found a little gem of a function called SerializeFromMismatchedTag.

It isn’t virtual, so it will only get called through the magic of turning on a flag for your struct using the following secondary struct declaration…

template<>
struct TStructOpsTypeTraits<FRelativeTime>
	: public TStructOpsTypeTraitsBase2<FRelativeTime>
{
	enum
	{
		WithSerializeFromMismatchedTag = true,
	};
};

Once you’ve declared that, SerializeFromMismatchedTag will get called. It allows you to convert another property type to your struct. Here is my implemenation…

// backward compatibility for when m_Start/EndTime was a simple float
bool FRelativeTime::SerializeFromMismatchedTag(struct FPropertyTag const& Tag, FArchive& Ar)
{
	if (Tag.Type == NAME_FloatProperty)
	{
		float Value;
		Ar << Value;
		SetAbsoluteTime(Value);
		return true;
	}

	return false;
}

Hope this helps someone. :slight_smile:

1 Like

Brilliant. I was always wondering how to do this. This has saved me from so many headaches.