Skip to content

Instantly share code, notes, and snippets.

@grisevg
Last active August 30, 2023 02:49
Show Gist options
  • Save grisevg/beaf25a85bb6ce005b17 to your computer and use it in GitHub Desktop.
Save grisevg/beaf25a85bb6ce005b17 to your computer and use it in GitHub Desktop.
UMG Animated Image.
#include "AnimatedImage.h"
void UAnimatedImage::SetCurrentFrame(int32 Frame)
{
CurrentFrame = Frame;
if (CurrentFrame < 0) CurrentFrame = 0;
if (CurrentFrame > TotalFrames - 1) CurrentFrame = TotalFrames - 1;
SynchronizeProperties();
}
void UAnimatedImage::Play()
{
if (!TimerHandle.IsValid())
{
GetWorld()->GetTimerManager().SetTimer(
TimerHandle,
this,
&UAnimatedImage::TimerTick,
1.0f / FramesPerSecond,
true
);
}
}
void UAnimatedImage::Stop()
{
if (TimerHandle.IsValid())
{
GetWorld()->GetTimerManager().ClearTimer(TimerHandle);
TimerHandle.Invalidate();
}
}
void UAnimatedImage::SynchronizeProperties()
{
Super::SynchronizeProperties();
UTexture2D* Texture = Cast<UTexture2D>(Brush.GetResourceObject());
if (Texture == nullptr) return;
FVector2D TextureSize(Texture->GetSizeX(), Texture->GetSizeY());
int32 MaxColumns = FMath::FloorToInt(TextureSize.X / Brush.ImageSize.X);
int32 Row = FMath::FloorToInt(CurrentFrame / MaxColumns);
int32 Column = CurrentFrame % MaxColumns;
FVector2D Min(Brush.ImageSize.X * Column, Brush.ImageSize.Y * Row);
FVector2D Max = Min + Brush.ImageSize;
FBox2D UVCoordinates(Min / TextureSize, Max / TextureSize);
UVCoordinates.bIsValid = true;
Brush.SetUVRegion(MoveTemp(UVCoordinates));
}
void UAnimatedImage::TimerTick()
{
CurrentFrame++;
if (CurrentFrame > TotalFrames - 1) CurrentFrame = 0;
SynchronizeProperties();
}
#pragma once
#include "Runtime/UMG/Public/UMG.h"
#include "Runtime/UMG/Public/UMGStyle.h"
#include "Runtime/UMG/Public/Slate/SObjectWidget.h"
#include "Runtime/UMG/Public/IUMGModule.h"
#include "Runtime/UMG/Public/Blueprint/UserWidget.h"
#include "Components/Image.h"
#include "AnimatedImage.generated.h"
/**
* UMG Animated Image.
* Make sure you add "UMG", "Slate" and "SlateCore" to your module's dependencies.
* It doesn't use flipbook data. All animation frames must be the same size and position in grid on the texture.
* Set frame size by setting "Image Size" and "Total Frames" http://i.imgur.com/5WuZmKA.png
*/
UCLASS()
class UAnimatedImage : public UImage
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = Animation)
void SetCurrentFrame(int32 Frame);
UFUNCTION(BlueprintCallable, Category = Animation)
void Play();
UFUNCTION(BlueprintCallable, Category = Animation)
void Stop();
virtual void SynchronizeProperties();
protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Animation)
int32 FramesPerSecond = 10;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Animation)
int32 CurrentFrame = 0;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Animation)
int32 TotalFrames = 1;
void TimerTick();
FTimerHandle TimerHandle;
};
@eanticev
Copy link

To get this to compile make sure to add UMG to your PublicDependencyModuleNames and Slate SlateCore to your PrivateDependencyModuleNames

        PublicDependencyModuleNames.AddRange(new string[] { 
		"Core", 
		"CoreUObject",
            	"Engine",
            	"InputCore", 
            	"UMG" // <---- THIS
        });
        
        DynamicallyLoadedModuleNames.Add("OnlineSubsystemNull");
        
        PrivateDependencyModuleNames.AddRange(new string[] {
            "Slate", // <---- THIS
            "SlateCore" // <---- THIS
        });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment