Download

🌞 Victory Plugin ~ Rama's Extra Blueprint Nodes for UE5, No C++ Required!

Victory Plugin For UE5

Latest Node Addition

You Can Easily Create Save Game Images With Victory Plugin for UE5!

Dear Community,

I am making my Victory Plugin for UE5!

Please let me know which VictoryPlugin nodes you want most from the UE4 version and I can work on bringing them into UE5!

Download Link

Rama’s Victory Plugin for UE5 Early Access 2

Get File And Folder Paths, Load Object From Path, Get OS Clipboard String & More!

Here is my initial Gift of nodes for UE5:

        //~~~~~~~~~~~~~~~~~~~
	// 	  Load Object
	//~~~~~~~~~~~~~~~~~~~
	
	/** The FName that is expected is the exact same format as when you right click on asset -> Copy Reference! You can directly paste copied references into this node! IsValid lets you know if the path was correct or not and I was able to load the object. MAKE SURE TO SAVE THE RETURNED OBJECT AS A VARIABLE. Otherwise your shiny new asset will get garbage collected. I recommend you cast the return value to the appropriate object and then promote it to a variable :)  -Rama */
	UFUNCTION(BlueprintCallable, Category = "Victory BP Library|Misc", Meta = (DeterminesOutputType = "ObjectClass"))
	static UObject* LoadObjectFromAssetPath(TSubclassOf<UObject> ObjectClass, FName Path, bool& IsValid);

	/** Uses the same format as I use for LoadObjectFromAssetPath! Use this node to get the asset path of objects in the world! -Rama */
	UFUNCTION(BlueprintPure, Category = "Victory BP Library|Misc")
	static FName GetObjectPath(UObject* Obj);
	
	//~~~~~~~~~~~~
	// 	  Math
	//~~~~~~~~~~~~
	
	/** Easily add to an integer! <3 Rama*/
	UFUNCTION(BlueprintCallable, meta = (CompactNodeTitle = "+=",Keywords = "increment integer"), Category = "Victory BP Library|Math|Integer")
	static void VictoryIntPlusEquals(UPARAM(ref) int32& Int, int32 Add, int32& IntOut);

	/** Easily subtract from an integer! <3 Rama*/
	UFUNCTION(BlueprintCallable, meta = (CompactNodeTitle = "-=",Keywords = "decrement integer"), Category = "Victory BP Library|Math|Integer")
	static void VictoryIntMinusEquals(UPARAM(ref) int32& Int, int32 Sub, int32& IntOut);

	/** Easily add to a float! <3 Rama*/
	UFUNCTION(BlueprintCallable, meta = (CompactNodeTitle = "+=",Keywords = "increment float"), Category = "Victory BP Library|Math|Float")
	static void VictoryFloatPlusEquals(UPARAM(ref) float& Float, float Add, float& FloatOut);

	/** Easily subtract from a float! <3 Rama*/
	UFUNCTION(BlueprintCallable, meta = (CompactNodeTitle = "-=",Keywords = "decrement float"), Category = "Victory BP Library|Math|Float")
	static void VictoryFloatMinusEquals(UPARAM(ref) float& Float, float Sub, float& FloatOut);
	
	//~~~~~~~~~~~~
	// 	  UMG
	//~~~~~~~~~~~~
	/**
	 * Find first widget of a certain class and return it.
	 * @param WidgetClass The widget class to filter by.
	 * @param TopLevelOnly Only a widget that is a direct child of the viewport will be returned.
	 */
	UFUNCTION(Category = "Victory BP Library|UMG", BlueprintCallable, BlueprintCosmetic, Meta = (WorldContext = "WorldContextObject", DeterminesOutputType = "WidgetClass"))
	static UUserWidget* GetFirstWidgetOfClass(UObject* WorldContextObject, TSubclassOf<UUserWidget> WidgetClass, bool TopLevelOnly);
	
	UFUNCTION(Category = "Victory BP Library|UMG", BlueprintCallable, BlueprintCosmetic, Meta = (DefaultToSelf = "ParentWidget", DeterminesOutputType = "WidgetClass", DynamicOutputParam = "ChildWidgets"))
	static void WidgetGetChildrenOfClass(UWidget* ParentWidget, TArray<UUserWidget*>& ChildWidgets, TSubclassOf<UUserWidget> WidgetClass, bool bImmediateOnly);
	 
	//~~~~~~~~~~~~
	// 	File I/O
	//~~~~~~~~~~~~

	UFUNCTION(BlueprintCallable, Category = "Victory BP Library|File IO")
	static FDateTime Victory_GetFileTimeStamp(const FString& File);
	
	UFUNCTION(BlueprintCallable, Category = "Victory BP Library|File IO")
	static void Victory_SetTimeStamp(const FString& File, const FDateTime& TimeStamp);

	/** Obtain all files in a provided directory, with optional extension filter. All files are returned if Ext is left blank. Returns false if operation could not occur. */
	UFUNCTION(BlueprintPure, Category = "Victory BP Library|File IO")
	static bool Victory_GetFiles(TArray<FString>& Files, FString RootFolderFullPath, FString Ext);

	/** Obtain all files in a provided root directory, including all subdirectories, with optional extension filter. All files are returned if Ext is left blank. The full file path is returned because the file could be in any subdirectory. Returns false if operation could not occur. */
	UFUNCTION(BlueprintPure, Category = "Victory BP Library|File IO")
	static bool Victory_GetFilesInRootAndAllSubFolders(TArray<FString>& Files, FString RootFolderFullPath, FString Ext);
	
	//~~~~~~~~~~
	// 	OS
	//~~~~~~~~~~
	
	UFUNCTION(BlueprintPure, Category = "Victory BP Library|String")
	static void Victory_GetStringFromOSClipboard(FString& FromClipboard);

	UFUNCTION(BlueprintCallable, Category = "Victory BP Library|String")
	static void Victory_SaveStringToOSClipboard(const FString& ToClipboard);
	
	/** Is the Current Game Window the Foreground window in the OS, or in the Editor? This will be accurate in standalone running of the game as well as in the editor PIE */
	UFUNCTION(BlueprintPure, Category = "Victory BP Library|Game Window")
	static bool ClientWindow__GameWindowIsForeGroundInOS();
	
	//~~~~~~~~~~~~~~
	// 	Windows OS
	//~~~~~~~~~~~~~~
	
	/** Flashes the game on the windows OS task bar! Please note this won't look the best in PIE, flashing is smoother in Standalone or packaged game. You can use GameWindowIsForeGroundInOS to see if there is a need to get the user's attention! <3 Rama */
	UFUNCTION(BlueprintCallable, Category = "Victory BP Library|Game Window")
	static void FlashGameOnTaskBar(APlayerController* PC, bool FlashContinuous=false, int32 MaxFlashCount = 3, int32 FlashFrequencyMilliseconds=500);

Table Of Contents Of Victory BP Nodes

  1. Save CaptureComponent2D To File, Load Image From File

Yay for UE5!

:heart:

Rama

17 Likes

Thank you for UE5 support!
First thing came to my mind are sorting float/integer arrays, sorting alphabetically would be great!

“Thank you for UE5 support!”

You’re welcome!

Annnnnnd, here you go!

Now You Can Sort Float, Integer, and String Arrays In UE5!

Victory to you @Emrehan !

:heart:

Rama

PS: Download link is in original post!

3 Likes

Thank you RAMA for your support :))
I like it very much “Capture component 2d save image” I use it for save slots

Dear @vladislav42 ,

I had a feeling this one was going to come up quick, okay I will work on this soon!

:heart:

Rama

You Can Easily Create Save Game Images With Victory Plugin for UE5!

Save Scene Capture To PNG

T2D Render Format, I highly recommend RTF RGBA8 SRGB, as this will have the same output as the way your in-game camera looks! <3 Rama

Please note I attached the SceneCaptureComponent2D to the Camera of the Character, so it will see what the camera sees :slight_smile:

Also note I am using Final Color HDR to include Post Processing Effects.

Performance

I recommend enabling and disabling tick on the SceneCaptureComponent so that it is only active while you are processing the user’s request to save the game. The advantage of this setup is simplicty, but for benefit of that simplicity you should be careful to manage the ticking of the SceneCaptureComponent2D for optimum performance :slight_smile:

Saving the Scene Capture as JPG to file!

Load PNG To T2D

Loading Image to UI!


C++ Code

.h

/** Load a Texture2D from a JPG,PNG,BMP,ICO,EXR,ICNS file! IsValid tells you if file path was valid or not. The image type is assumed from an extension such as .jpg, .png, .bmp. Enjoy! -Rama */
	UFUNCTION(BlueprintCallable, Category = "Victory BP Library|Load Texture From File",meta=(Keywords="image png jpg jpeg bmp bitmap ico icon exr icns"))
	static UTexture2D* Victory_LoadTexture2D_FromFileByExtension(const FString& FullFilePath,bool& IsValid, int32& Width, int32& Height);

/** 
		I highly recommend that your Texture Render Target Format be "RTF RGB8 SRGB" both so it is compatible, and so it looks the same as in-game 
			<3 Rama. 
			
		Make sure to include the appropriate image extension in your file path! Recommended: .bmp, .jpg, .png. Contributed by Community Member Kris! 
	*/
	UFUNCTION(Category = "Victory BP Library|SceneCapture", BlueprintCallable)
	static bool CaptureComponent2D_SaveImage(class USceneCaptureComponent2D* Target, const FString ImagePath, const FLinearColor ClearColour);	

.cpp

static TSharedPtr<IImageWrapper> GetImageWrapperByExtention(const FString InImagePath)
{
	//EndsWith is not case sensitive by default, see unrealstring.h btw -Rama
	
    IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
    if (InImagePath.EndsWith(".png"))
    {
        return ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);
    }
    else if (InImagePath.EndsWith(".jpg") || InImagePath.EndsWith(".jpeg"))
    {
        return ImageWrapperModule.CreateImageWrapper(EImageFormat::JPEG);
    }
    else if (InImagePath.EndsWith(".bmp"))
    {
        return ImageWrapperModule.CreateImageWrapper(EImageFormat::BMP);
    }
    else if (InImagePath.EndsWith(".ico"))
    {
        return ImageWrapperModule.CreateImageWrapper(EImageFormat::ICO);
    }
    else if (InImagePath.EndsWith(".exr"))
    {
        return ImageWrapperModule.CreateImageWrapper(EImageFormat::EXR);
    }
    else if (InImagePath.EndsWith(".icns"))
    {
        return ImageWrapperModule.CreateImageWrapper(EImageFormat::ICNS);
    }
    
    return nullptr;
}

static UTexture2D* LoadTexture2D(const FString& FullFilePath, TSharedPtr<IImageWrapper> ImageWrapper, bool& IsValid, int32& Width, int32& Height)
{
	IsValid = false;
	UTexture2D* LoadedT2D = NULL;
	
	
	//Load From File
	TArray<uint8> RawFileData;
	if (!FFileHelper::LoadFileToArray(RawFileData, *FullFilePath)) 
	{
		return NULL;
	}
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	  
	//Create T2D!
	if (ImageWrapper.IsValid() && ImageWrapper->SetCompressed(RawFileData.GetData(), RawFileData.Num()))
	{ 
		TArray<uint8> UncompressedBGRA;
		if (ImageWrapper->GetRaw(ERGBFormat::BGRA, 8, UncompressedBGRA))
		{
			LoadedT2D = UTexture2D::CreateTransient(ImageWrapper->GetWidth(), ImageWrapper->GetHeight(), PF_B8G8R8A8);
			
			//Valid?
			if(!LoadedT2D) 
			{
				return NULL;
			}
			//~~~~~~~~~~~~~~
			
			//Out!
			Width = ImageWrapper->GetWidth();
			Height = ImageWrapper->GetHeight();
			 
			//Copy!
			void* TextureData = LoadedT2D->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
			FMemory::Memcpy(TextureData, UncompressedBGRA.GetData(), UncompressedBGRA.Num());
			LoadedT2D->PlatformData->Mips[0].BulkData.Unlock();

			//Update!
			LoadedT2D->UpdateResource();
		}
	}
	  
	// Success!
	IsValid = true;
	return LoadedT2D;
}

UTexture2D* UVictoryBPFunctionLibrary::Victory_LoadTexture2D_FromFile(const FString& FullFilePath,EJoyImageFormats ImageFormat,bool& IsValid, int32& Width, int32& Height)
{
	IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
	TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(GetJoyImageFormat(ImageFormat));
	
	return LoadTexture2D(FullFilePath,ImageWrapper,IsValid,Width,Height);
}

UTexture2D* UVictoryBPFunctionLibrary::Victory_LoadTexture2D_FromFileByExtension(const FString& FullFilePath,bool& IsValid, int32& Width, int32& Height)
{
	TSharedPtr<IImageWrapper> ImageWrapper = GetImageWrapperByExtention(FullFilePath);
	
	return LoadTexture2D(FullFilePath,ImageWrapper,IsValid,Width,Height);
}

bool UVictoryBPFunctionLibrary::CaptureComponent2D_SaveImage(class USceneCaptureComponent2D* Target, const FString ImagePath, const FLinearColor ClearColour)
{ 
	// Bad scene capture component! No render target! Stay! Stay! Ok, feed!... wait, where was I?
	if ((Target == nullptr) || (Target->TextureTarget == nullptr))
	{
		#if WITH_EDITOR
			FMessageLog("PIE").Error(FText::Format(LOCTEXT("CaptureComponent2D_SaveImage", "UVictoryBPFunctionLibrary::CaptureComponent2D_SaveImage >> Please supply a Capture Component with a valid T2D Render Target :) <3 Rama {0}'"), FText::FromString(ImagePath)));
		#endif // WITH_EDITOR
		
		return false;
	}
	
	FRenderTarget* RenderTarget = Target->TextureTarget->GameThread_GetRenderTargetResource();
	if (RenderTarget == nullptr)
	{
		return false;
	}

	TArray<FColor> RawPixels;
	
	// Format not supported - use PF_B8G8R8A8.
	if (Target->TextureTarget->GetFormat() != PF_B8G8R8A8)
	{
		#if WITH_EDITOR
			FMessageLog("PIE").Error(FText::Format(LOCTEXT("CaptureComponent2D_SaveImage", "UVictoryBPFunctionLibrary::CaptureComponent2D_SaveImage >> The Texture Render Target (the texture render asset itself) format is not supported - use PF_B8G8R8A8 <3 Rama & Kris: {0}'"), FText::FromString(ImagePath)));
		#endif // WITH_EDITOR
		
		return false;
	}

	if (!RenderTarget->ReadPixels(RawPixels))
	{
		return false;
	}

	// Convert to FColor.
	FColor ClearFColour = ClearColour.ToFColor(false); // FIXME - want sRGB or not?

	for (auto& Pixel : RawPixels)
	{
		// Switch Red/Blue changes.
		const uint8 PR = Pixel.R;
		const uint8 PB = Pixel.B;
		Pixel.R = PB;
		Pixel.B = PR;

		// Set alpha based on RGB values of ClearColour.
		Pixel.A = ((Pixel.R == ClearFColour.R) && (Pixel.G == ClearFColour.G) && (Pixel.B == ClearFColour.B)) ? 0 : 255;
	}
	
	TSharedPtr<IImageWrapper> ImageWrapper = GetImageWrapperByExtention(ImagePath);

	const int32 Width = Target->TextureTarget->SizeX;
	const int32 Height = Target->TextureTarget->SizeY;
	
	if (ImageWrapper.IsValid() && ImageWrapper->SetRaw(&RawPixels[0], RawPixels.Num() * sizeof(FColor), Width, Height, ERGBFormat::RGBA, 8))
	{
		return FFileHelper::SaveArrayToFile(ImageWrapper->GetCompressed(), *ImagePath);
	}
	
	return false;
}

Additional Pics

Here are some additional pics I took, notice they have square dimensions, as those were the settings in the Texture Render Target (2048x2048). You can change the Texture Render Target dimensions to whatever you like :slight_smile:

:heart:

Rama

PS: @vladislav42 Thanks for the request! Enjoooy!

PSS: Download link is in original post!

IT IS EXCELLENT!!!
RAMA thank you so much, I really love this :heart_eyes: :smiling_face_with_three_hearts:

1 Like

Rama <3 :heart_eyes::heart_eyes::heart_eyes:

Do you mind adding back : “get all bone names below bone”
when you have time? :slight_smile:
Thank you !

Do you mind adding back : “Victory_LoadTexture2D_FromFile ”
when you have time? :slight_smile:
Thank you !

Hi there!

Yes I’ve added back that node, and also a new one, here’s C++ header:

//~~~~~~~~~~~~~~~~
	//  Image Files!
	//~~~~~~~~~~~~~~~~
	
	/** Load a Texture2D from a JPG,PNG,BMP,ICO,EXR,ICNS file! IsValid tells you if file path was valid or not. Enjoy! -Rama */
	UFUNCTION(BlueprintCallable, Category = "Victory BP Library|Load Texture From File",meta=(Keywords="image png jpg jpeg bmp bitmap ico icon exr icns"))
	static UTexture2D* Victory_LoadTexture2D_FromFile(const FString& FullFilePath,EJoyImageFormats ImageFormat,bool& IsValid, int32& Width, int32& Height);
	
	/** Load a Texture2D from a JPG,PNG,BMP,ICO,EXR,ICNS file! IsValid tells you if file path was valid or not. The image type is assumed from an extension such as .jpg, .png, .bmp. Enjoy! -Rama */
	UFUNCTION(BlueprintCallable, Category = "Victory BP Library|Load Texture From File",meta=(Keywords="image png jpg jpeg bmp bitmap ico icon exr icns"))
	static UTexture2D* Victory_LoadTexture2D_FromFileByExtension(const FString& FullFilePath,bool& IsValid, int32& Width, int32& Height);

And I use the ByExtension version in this tutorial:

Enjoy!

:heart:

Rama

I have now added this node! :slight_smile:

/**
	 * Get All Bone Names Below Bone, requires a physics asset, by Rama
	 *
	 * @param StartingBoneName The name of the bone to find all bones below.
	 *
	 * @param BoneNames , all of the bone names below the starting bone.
	 *
	 * @return total number of bones found
	 */
	UFUNCTION(BlueprintCallable, Category="Victory BP Library|Components|SkinnedMesh")
	static int32 GetAllBoneNamesBelowBone(USkeletalMeshComponent* SkeletalMeshComp, FName StartingBoneName,  TArray<FName>& BoneNames );

Enjoooy!

:heart:

Rama

1 Like

your the best thank you so muchhhhhhhh <3 <3 :smiling_face_with_three_hearts:

Do you mind adding … it all back ? lol - The project I am working on is heavily dependent on the victory plugin but maybe for now just “Animation Aim Offset” will suffice. Thank you ! :smiley:

2 Likes

Thank you very much

Hee hee, you’re welcome!

I am a little crimped for time these days and things are a bit different in UE5 so I have to do each node carefully, buuuut, if you give me a list of the nodes you need I can focus on those first!

I will process aim offset soon!

:heart:

Rama

Dear Rama,

I had to look through every single node I am using because your library is so good I can’t tell it apart from vanilla nodes!
Get Closest Actor Of Class In Radius Of Location, (string) Append Multiple, Viewport Position Deproject, and Widget Get Parent Of Class are the blueprints I am using at the moment, if you could find the time to add these to the UE5 version, that would be awesome! Happy coding!

1 Like

Sweet!

However, it appears this is missing a bunch of nodes? Maybe I have to rethink some entire chunks of code due to the new UE5 stuff, but I’m missing the following nodes:

  • Get Level Instance Info
  • A structure related to this (I can’t recall the struct type, Level Info or something?)
  • Server Travel (Is this a UE4 node or Victory node?)
  • Add to Streaming Levels

Possibly a couple others but I think that’s the main ones. I have a small prototype that heavily used these nodes, I wonder if the implementation will have to drastically change in UE5.

Thank you very much for your work. I’ve migrated my 4.26 project to unreal 5, but can’t find all the
previous nodes. I’ve deleted all the victory nodes I had in my blueprints, but still can’t open ue5 version.
Can you tell me how to remove all the references to the plugin from the blueprints?
Thanks.

1 Like

Solved! I had an “append multiple” node. To find it I exported the blueprint in ascii (.copy extension) and checked for “victory” with notepad++.

Rama,

First off thanks for all the help and time supported to the UE community.

Secondly, could you bring back create process node.

Ty.