UMG Widget Image Tiling

Is it possible to tile image how i want in UMG Widget using blueprints in runtime? For example i have an image with lot’s of icons and want to set correct position for x/y in blueprints for them depends on game conditions (inventory, hud, other stuff, etc). Seems Slate Brush gives only one option - Tiling (horizontal, both, etc) and size, but i can’t set UV coords using it. In Shooter Game with C++ for example same things is done with just Canvas->DrawIcon method and FCanvasIcon structure, i found MakeCanvasIcon and Break nodes, but have no idea how to use it, seems it’s just added without any references to anything and unused. Ye, i guess using materials tiling or hud drawtexture this probably can be done some way or another with pain in ***, but is there any simplier way i’m missing specificly for UMG?

The solution to this was only coding, how to archive quick results, get rama custom UMG component https://wiki.unrealengine.com/UMG,_C…B_Code_for_You
Get rid of few outdated things…



 //#include "Abatron.h" //comment this 

SSoftEdgeImage.h

if errors with SLATE_ATTRIBUTE in , as i had, use this in header instead:


TAttribute <const FSlateBrush*> _Image;
        TAttribute <FSlateColor> _ColorAndOpacity;
        TAttribute <float> _Thickness;

SSoftEdgeImage.cpp

Define:



#define SLATE_HD_STATS 0


replace



 const FColor FinalColorAndOpacity( InWidgetStyle.GetColorAndOpacityTint() * ColorAndOpacity.Get().GetColor(InWidgetStyle) * ImageBrush->GetTint( InWidgetStyle ) ); 

with



        const FLinearColor FinalColorAndOpacity = InWidgetStyle.GetColorAndOpacityTint() * ColorAndOpacity.Get().GetColor(InWidgetStyle) * TempBrush->GetTint(InWidgetStyle);


Or just use my own crappy code, replace method with this in SSoftEdgeImage.cpp:


int32 SSoftEdgeImage::OnPaint( const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled ) const
{
#if SLATE_HD_STATS
    SCOPE_CYCLE_COUNTER( STAT_SlateOnPaint_SSoftEdgeImage );
#endif

    ////////////////////////////
    const FSlateBrush* ImageBrush = Image.Get();

    FSlateBrush* TempBrush = const_cast <FSlateBrush*>(ImageBrush);

    FVector2D FMin, FMax;

    FMin.Set(MinX, MinY);
    FMax.Set(MaxX, MaxY);

    const FBox2D ImageBox(FMin, FMax);

    TempBrush->SetUVRegion(ImageBox);


    if ((TempBrush != nullptr) && (TempBrush->DrawAs != ESlateBrushDrawType::NoDrawType))
    {
        const bool bIsEnabled = ShouldBeEnabled(bParentEnabled);
        auto DrawEffects = bIsEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect;

        const FLinearColor FinalColorAndOpacity = InWidgetStyle.GetColorAndOpacityTint() * ColorAndOpacity.Get().GetColor(InWidgetStyle) * TempBrush->GetTint(InWidgetStyle);
        //const FColor FinalColorAndOpacity(FLColor.ToFColor(true));

        //For Thickness
        for (int32 v = 0; v < Thickness; v++ )
        {          
            //Size
            FVector2D AdjustedSize =
                FVector2D(
                    AllottedGeometry.GetLocalSize().X - v*2,
                    AllottedGeometry.GetLocalSize().Y - v*2
                );

            //There's a warning about using this constructor in Geometry.h
            //        But it looks like the code was fixed in Geometry.cpp to use layout transform properly. Plus all render transforms work great in Editor.
            //            So keeping this for now :)
            FPaintGeometry PaintGeom =
                AllottedGeometry.ToPaintGeometry(
                    FVector2D(v,v),        //Local Translation
                    AdjustedSize,        //Local Size
                    1            //Local Scale
                );

            FSlateDrawElement::MakeBox(
                OutDrawElements,
                LayerId,
                PaintGeom,
                TempBrush,
                //MyClippingRect,         //Clip ???
                DrawEffects,
                FinalColorAndOpacity
            );

        } //For loop
    }
    return LayerId;
}

SSoftEdgeImage.h
in public:



    void Set_UV_MinX(float MinX);
    void Set_UV_MinY(float MinY);
    void Set_UV_MaxY(float MaxY);
    void Set_UV_MaxX(float MaxX);


    float MinX = 0;
    float MinY = 0;
    float MaxX = 1;
    float MaxY = 0;


JoySoftEdgeImage.h


public:
    /** Thickness */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Joy Soft Edge Image")
    float Thickness;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Joy Soft Edge Image")
        float MinX;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Joy Soft Edge Image")
        float MinY;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Joy Soft Edge Image")
        float MaxX;
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Joy Soft Edge Image")
        float MaxY;

        //Delegate verison if you want it!
    //        -Rama
    //PROPERTY_BINDING_IMPLEMENTATION(float, Thickness);

    /** Update thickness of Soft Edge Image! Yay! */
    UFUNCTION(BlueprintCallable, Category="Joy Soft Edge Image")
    void SetThickness(float InThickness);

    /** Update uv */
    UFUNCTION(BlueprintCallable, Category = "Joy Soft Edge Image")
        void Set_UV_MinX(float uvMinX);
    UFUNCTION(BlueprintCallable, Category = "Joy Soft Edge Image")
        void Set_UV_MinY(float uvMinX);
    UFUNCTION(BlueprintCallable, Category = "Joy Soft Edge Image")
        void Set_UV_MaxX(float uvMaxX);
    UFUNCTION(BlueprintCallable, Category = "Joy Soft Edge Image")
        void Set_UV_MaxY(float uvMaxY);

//~~~ Rest is copied from UMG Image.h ~~~
public:

    /** Image to draw */
    //UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category=Appearance)
    UPROPERTY(EditAnywhere, Category=Appearance)
    FSlateBrush Brush;

    /** A bindable delegate for the Image. */
    UPROPERTY()
    FGetSlateBrush BrushDelegate;

    /** Color and opacity */
    //UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category=Appearance)
    UPROPERTY(EditAnywhere, Category=Appearance)
    FLinearColor ColorAndOpacity;

In JoySoftEdgeImage.cpp


void UJoySoftEdgeImage::Set_UV_MinX(float uvMinX)
{
    MinX = uvMinX;
    if (MyImage.IsValid())
    {
        MyImage->Set_UV_MinX(uvMinX);
    }
}

void UJoySoftEdgeImage::Set_UV_MinY(float uvMinY)
{
    MinY = uvMinY;
    if (MyImage.IsValid())
    {
        MyImage->Set_UV_MinY(uvMinY);
    }
}

void UJoySoftEdgeImage::Set_UV_MaxX(float uvMaxX)
{
    MaxX = uvMaxX;
    if (MyImage.IsValid())
    {
        MyImage->Set_UV_MaxX(uvMaxX);
    }
}

void UJoySoftEdgeImage::Set_UV_MaxY(float uvMaxY)
{
    MaxY = uvMaxY;
    if (MyImage.IsValid())
    {
        MyImage->Set_UV_MaxY(uvMaxY);
    }
}


void UJoySoftEdgeImage::SynchronizeProperties()
{
    Super::SynchronizeProperties();

        //Thickness Delegate Version
    //TAttribute<float> ThickBind = PROPERTY_BINDING(float, Thickness);
    //MyImage->SetThickness(ThickBind.Get());  

    //Thickness non-delegate version
    MyImage->SetThickness(Thickness);

    MyImage->Set_UV_MinX(MinX);
    MyImage->Set_UV_MinY(MinY);
    MyImage->Set_UV_MaxX(MaxX);
    MyImage->Set_UV_MaxY(MaxY);
  ...
}


Now y will be able manually manipulate image UV values with custom ui component and set it through blueprints how y want.