Having trouble storing a UPROPERTY value

I am trying to make a version of Image Widget that automatically converts the brush into a dynamic material for further customization.
In my implementation I do this by extending the Image class and do the conversion on SynchronizeProperties.

Below is a minimized version of my code


UCLASS()
class GAME_API UMaterialImage : public UImage
{
    GENERATED_BODY()

    public:
    virtual void SynchronizeProperties() override;

    UPROPERTY(BlueprintReadOnly, Transient, Category=Appearance)
    UMaterialInstanceDynamic* DynamicMaterial;

    UPROPERTY(EditAnywhere, BlueprintReadOnly)
    UObject* OriginalResource;
};


void UMaterialImage::SynchronizeProperties()
{
    UObject* Resource = Brush.GetResourceObject();

    if (!Resource && OriginalResource)
        Resource = OriginalResource;

    if (Resource)
    {
        DynamicMaterial = Cast<UMaterialInstanceDynamic>(Resource);

        if(!DynamicMaterial)
        {
            auto MaterialInterface = Cast<UMaterialInterface>(Resource);

            if (MaterialInterface)
            {
                OriginalResource = Resource;

                DynamicMaterial = GetDynamicMaterial();
            }
        }
    }
}

The idea is not to store the dynamic material, but instead store the resource that was applied to the brush before conversion and do the conversion again on load.

I though having OriginalResource be a UPROPERTY would make it store the data, but it just resets it back to null whenever I compile the Widget Blueprint and the data is missing when saving as well.

Manually setting the property using the Details panel works, but that kinda defeats the point. The intention is for the OriginalResource property to be assigned trough the conversion and hidden from the Details panel, it is just made visible for debugging.

Is it possible to set UPROPERTIES from code and have it store that value, or can it only work by setting it using the Details Panel?
Or is there a different approach that would give the result that I should do instead?

UPROPERTIES are just properties, so yes, you can set them from code. The issue you are having is you aren’t saving the asset after the value is changed. You would need to call Modify or MarkAsDirty on the asset after you change that value.



if (MaterialInterface)
{
#if WITH_EDITOR
    Modify();    
#endif
    OriginalResource = Resource;

    DynamicMaterial = GetDynamicMaterial();
}


Hi ExtraLifeMatt, thanks for helping, I tried your suggestion, but unfortunately it did not work.

I added logs at the start and end of SynchronizeProperties to verify that OriginalResource is indeed set when assigning a material to the brush, and is null at the start after compiling.
It is also apparent by looking at OriginalResource property the Details panel.

Did also try moving the Modify function to be after assigning OriginalResource and with bAlwaysMarkDirty set to true, but it didn’t make any difference.

Hi everyone, after trying some more I eventually gave up and changed my approach and got something working now.
I decided to apply the DynamicMaterial to a separate FSlateBrush and apply that brush to MyImage instead.
The new brush is Transient and generated on load based on the content of the original brush.

This makes the data store properly, but now I have to target the correct brush when animating the material inside the UserWidget, not ideal, but it works.