Download

(39) Rama's Extra Blueprint Nodes for You as a Plugin, No C++ Required!

After 4.8 happens things will be easier, for now just add an empty Actor class to your project via File->Add Code to project or using the 4.7 way of adding code.

Then my plugin will get compiled when your game gets packaged!

Thanks for suggestion John!

I will write this down to do :slight_smile:

Yes I am working on my Load Image node right now actually!

Async = great idea!

option for no mip maps = great idea!

Right now I am trying to get the pixels :slight_smile:

I can multi thread the loading of the image, the issue will be how your BP code will be told properly when the loading process has finished

I will probably need an UImageLoader component to organize this and you can ping this Victory Image Loader to to ask it if it has finished loading everything.

This component could be added to any actor / a new actor that gets spawned on level start

:slight_smile:

Rama

Hey Rama! Think you could bang out a node for making a Victory Key? Like we feed a string in the format your Key as String into this node and it gives us the Key struct back? We need to store our Keybindings in a database and storing them as strings would be best. We’d really appreciate it! Your BP nodes are the best!

Okay this will be the next thing I work on in my spare time, buuuuut check out my next poooost!

Load Image From File, and Retrieve All Pixel Data!

Dear Community,

As requested I’ve made a node that let’s you load an image from file, and get all the pixel data from the image for use in Blueprints!

Very conveniently, the pixel data comes in the Linear Color format so you can directly plug your pixels into Print string nodes or any other node that wants a color in UE4 Blueprints!!

This node is live as of April 17th, 2015 5:43am version!


**Bonus Just For You ~ Get Pixel by Coordinate!**

And as a bonus, just for you Community members, I've added a node that let's you specify a pixel coordinate and retrieves that value from the pixel data array!

Picture explanation

In the top picture I am loading an image at runtime, and then using print string to display the color values of different pixels within the image, notice how they match correctly in a 5 x 5 image! (it blurs cause of how textures work)


**BP Implementation**

![LoadImagePixels.jpg|1280x960](upload://x4rr84sVoeasRSMdQnWY13yUVvZ.jpeg)

![GetImagePixel.jpg|1280x960](upload://ywwata5V8Ypp8BnDKI1xqeuHKhi.jpeg)

Indices Start at 0,0

Please note that in the image that is 5 x 5, the lower right corner is 4,4 because picture indices start at 0,0 not 1,1.


**PNG Format**

Please make sure to use .png format for small images if you are wanting to use the pixel data to proceduraly generate world, jpg has compression quality loss that destroys pixel-level precision, especially for small files.

Plugin Download ( Tiny file, about 0.5 MB )

**Latest Download From the UE4 Wiki Site **


**My C++ Code For You**

Here's the C++ code for my new node!



```


UTexture2D* UVictoryBPFunctionLibrary::Victory_LoadTexture2D_FromFile_Pixels(const FString& FullFilePath,EJoyImageFormats ImageFormat,bool& IsValid, int32& Width, int32& Height, TArray<FLinearColor>& OutPixels)
{
	//Clear any previous data
	OutPixels.Empty();
	
	IsValid = false;
	UTexture2D* LoadedT2D = NULL;
	
	IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
	// Note: PNG format.  Other formats are supported
	IImageWrapperPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper(GetJoyImageFormat(ImageFormat));
 
	//Load From File
	TArray<uint8> RawFileData;
	if (!FFileHelper::LoadFileToArray(RawFileData, *FullFilePath)) return NULL;
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	  
	//Create T2D!
	if (ImageWrapper.IsValid() && ImageWrapper->SetCompressed(RawFileData.GetData(), RawFileData.Num()))
	{  
		const TArray<uint8>* UncompressedBGRA = NULL;
		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();
			
			const TArray<uint8>& ByteArray = *UncompressedBGRA;
			//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			
			for(int32 v = 0; v < ByteArray.Num(); v+=4) 
			{ 
				if(!ByteArray.IsValidIndex(v+3)) 
				{ 
					break;
				}   
				  
				const uint8& B = ByteArray[v];
				const uint8& G = ByteArray[v+1];
				const uint8& R = ByteArray[v+2];
				const uint8& A = ByteArray[v+3]; 
				
				OutPixels.Add(FLinearColor(R,G,B,A));
			}
			//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			   
			//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;
	
}


```



C++ Pixel Core

Here’s the core of my C++ code above where I turn the loaded byte array into Linear Color Pixel data!

Note how the provided format is BGRA so I have to re-arrange the values when I send them out to the FLinearColor constructor!



const TArray<uint8>& ByteArray = *UncompressedBGRA;

for(int32 v = 0; v < ByteArray.Num(); v+=4) 
{ 
	if(!ByteArray.IsValidIndex(v+3)) 
	{ 
		break;
	}   
	  
	const uint8& B = ByteArray[v];
	const uint8& G = ByteArray[v+1];
	const uint8& R = ByteArray[v+2];
	const uint8& A = ByteArray[v+3]; 
	
	OutPixels.Add(FLinearColor(R,G,B,A));
}



Enjoy!

♥

Rama

You truly are an unstoppable coding machine, Rama. Thank you! Can’t wait to try this out. Is this in the current download? Cheers!

J^2

Wait hold on a few minutes!, wait about 2-5 minutes and then get my latest version!

I just made the code more efficient by getting the byte data by const reference! :slight_smile:


**C++ Pixel Core**

Here's the core of my C++ code above where I turn the loaded byte array into Linear Color Pixel data!

**Note how the provided format is BGRA** so I have to re-arrange the values when I send them out to the FLinearColor constructor!



```


const TArray<uint8>& ByteArray = *UncompressedBGRA;

for(int32 v = 0; v < ByteArray.Num(); v+=4) 
{ 
	if(!ByteArray.IsValidIndex(v+3)) 
	{ 
		break;
	}   
	  
	const uint8& B = ByteArray[v];
	const uint8& G = ByteArray[v+1];
	const uint8& R = ByteArray[v+2];
	const uint8& A = ByteArray[v+3]; 
	
	OutPixels.Add(FLinearColor(R,G,B,A));
}


```



Plugin Download ( Tiny file, about 0.5 MB )

It’s ready now, top-most link, April 17th!

**Latest Download From the UE4 Wiki Site **

Rama

Excellent! Grabbing now. That’s very strange how they change the order of color channels. I never would have guessed that. Cheers,

J^2

Your question got me thinking, so I fixed the code and made it even more efficient! I am now loading the Texture2D in RGBA format, which is PF_R8G8B8A8.


**My C++ Code, Even More Faster Now!**

Notice how now I am not even storing the const references, **I am plugging directly into the FLinearColor constructor!**



```


UTexture2D* UVictoryBPFunctionLibrary::Victory_LoadTexture2D_FromFile_Pixels(const FString& FullFilePath,EJoyImageFormats ImageFormat,bool& IsValid, int32& Width, int32& Height, TArray<FLinearColor>& OutPixels)
{
	//Clear any previous data
	OutPixels.Empty();
	
	IsValid = false;
	UTexture2D* LoadedT2D = NULL;
	
	IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
	
	IImageWrapperPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper(GetJoyImageFormat(ImageFormat));
 
	//Load From File
	TArray<uint8> RawFileData;
	if (!FFileHelper::LoadFileToArray(RawFileData, *FullFilePath)) return NULL;
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	  
	//Create T2D!
	if (ImageWrapper.IsValid() && ImageWrapper->SetCompressed(RawFileData.GetData(), RawFileData.Num()))
	{  
		const TArray<uint8>* UncompressedRGBA = NULL;
		if (ImageWrapper->GetRaw(**ERGBFormat::RGBA**, 8, UncompressedRGBA))
		{
			LoadedT2D = UTexture2D::CreateTransient(ImageWrapper->GetWidth(), ImageWrapper->GetHeight(), ****PF_R8G8B8A8****);
			
			//Valid?
			if(!LoadedT2D) return NULL;
			//~~~~~~~~~~~~~~
			
			//Out!
			Width = ImageWrapper->GetWidth();
			Height = ImageWrapper->GetHeight();
			
			const TArray<uint8>& ByteArray = *UncompressedRGBA;
			//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			
			for(int32 v = 0; v < ByteArray.Num(); v+=4) 
			{ 
				if(!ByteArray.IsValidIndex(v+3)) 
				{ 
					break;
				}   
				     
				**OutPixels.Add(
					FLinearColor(
						ByteArray[v],		//R
						ByteArray[v+1],		//G
						ByteArray[v+2],		//B
						ByteArray[v+3] 		//A
					)
				);**
			}
			//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			   
			//Copy!
			void* TextureData = LoadedT2D->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
			FMemory::Memcpy(TextureData, UncompressedRGBA->GetData(), UncompressedRGBA->Num());
			LoadedT2D->PlatformData->Mips[0].BulkData.Unlock();

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


```



Load Image From File and Get Pixel Data!

New Node Release Post is here!


**Plugin Download** ( Tiny file, about 0.5 MB )

It's ready now, top-most link, April 17th!

**Latest Download From the UE4 Wiki Site **
https://wiki.unrealengine.com/File:VictoryPlugin.zip

♥

Rama

I am going to have to see if I can get an Earth map generated using this new node!

Just going to need specifically sized earth textures for each of the data types(Topology, Temperature, Precipitation, etc). Will post here if I make any progress. :slight_smile:

amazing stuff rama! used your ISM today and worked amazingly well.

Rama, your new name now is Ron Popeil now.

“But wait, there’s more!” :smiley:

Ah, that’s a nice trick using an empty actor to insert code. Thanks a bunch for the help, and for the work you’ve done on this plugin!

This is cool! First one to make a heightfield voxel landscape which is then turned into a highly efficient instanced mesh wins!

Quick proof of concept shows the plugin doing exactly what I need. I made a small 8x8 grid:

d54f24b06c6b346968764607e3fece353c559c82.png

I made a blueprint that loads the image and trolls through the pixel array. Wherever it finds a black pixel, I spawn a tree instance:

Simplicity itself. I now have precise control over the placement of objects in my scenes in a way that I can easily control through visual means. And I’m sure that’s just the start. Now, I will be able to use the same heightfield I use to make a hill or mountain tile mesh for Z’s map gen to control the placement of trees on that same mesh.

Rama, I love you. :slight_smile:

J^2

It lives! :slight_smile:

Source File:

Rama, I had to plug the Width from the Load Texture node to the Get Pixel node to get it to work(maybe something unique to my setup), but other than that great stuff!

I have only added in land/water data using an image. I could do the same thing for with topology, precipitation, etc. Nice to see that my weather system put deserts and jungles on the earth map where they belong though! :slight_smile:

You’re welcome YarnBallSoftware!

Woohooo! That’s awesome J^2 !!

Thanks for sharing the pic!

Glad you like my new BP node!

For others, its my Load Image And Get Pixels Combo!

Load Image w/ Pixels, and Get Pixel from Index

Rama

Wooohoo!

Awesome Zeustiak!

Thanks for sharing the pics!

Your procedural map looks wonderful!

:slight_smile:

Rama

Hi Rama!
You already know how we love your plugin, so let’s go with the requests! :wink:
A nice feature would be the ability to rename the filenames of screenshots (f.i. taken with the console command “HighResShot”) - and change the default destination folder as well, using string parameters for both.
Is it hard / impossibile / sci-fi? ;D

This is a great question!

I will look into this after I make a node that takes in a pixel array and converts it to various image types! (my next node plan)

But your request is great! Writing it down!

EDIT

I mapped out exactly how I’m gonna do it, will do it on my next work-break!


**Rama's Newest BP Node ~ Load Image And Get Pixel Data**

**This node lets you load all the pixel data from a image file at runtime!**
https://forums.unrealengine.com/showthread.php?3851-(39)-Rama-s-Extra-Blueprint-Nodes-for-You-as-a-Plugin-No-C-Required!&p=273611&viewfull=1#post273611

Rama

ScreenShots, Move or Rename Most Recent!

3ad170c1fdb5928f5f54c13a7fa4405b1e2a8d55.jpeg

Dear Community,

New node for you!

This node will move / rename the most recently taken screenshot!

So the intended work flow is

  1. Exec Console Command -> “HighResShot 2” or “shot showui”

  2. Possibly put in a short Delay node

  3. Use my new node! ScreenShots Move Rename Most Recent!


**More Power for You in BP**

Now you can specify an absolute path directory and also file name for the most recent screen shot, and it will be relocated for you!

So please note you can only do this **after** you create the image using UE4's console commands.

Bonus For You

You can specify a destination folder that does not exist yet and my node will create it for you!

This is great for if you delete your custom screen shots folder and expect my node to work anyway!

My node will!

:slight_smile:


**High Res vs Regular Screen Shots**

You can filter for High Resolution and regular screen shots independently using my node!

So if you have High Res selected, ONLY High Resolution screenshots are considered when sorting by file time.

Otherwise, if this is unchecked, I will ONLY look for regular screenshots taken with  "shot showui"

:)

Keep in Same Directory?

To keep the file in the same directory, use my new Paths node that retrieves your project’s ScreenShot directory!


**Pro Tip**

If you have a bunch of shots, you can:

1. use my node in a for loop with a break and a max count of 1000,  (or while loop if you are feeling confident)
2. Ensure that you are moving the files OUT of their current directory (otherwise for loop will run to its limit) 
3. The break condition is when my new node returns false, so just plug the false end of the branch right back into the break condition!

This will work because my node is only checking the dates of the files that are within the screenshots directory, so as you keep moving the files out, my node will keep finding the new most recent picture!

My C++ Code For You

I had to write a lot of custom File Operations code to fulfill this request, so a lot of the functions you see in this node are not stock UE4 code. :slight_smile:



bool UVictoryBPFunctionLibrary::ScreenShots_Rename_Move_Most_Recent(
	FString& OriginalFileName,
	FString NewName, 
	FString NewAbsoluteFolderPath, 
	bool HighResolution
){ 
	OriginalFileName = "None";

	**//File Name given?**
	if(NewName.Len() <= 0) return false;
	
	**//Normalize**
	FPaths::NormalizeDirectoryName(NewAbsoluteFolderPath);
	
	**//Ensure target directory exists, 
	//		_or can be created!_ <3 Rama**
	if(!VCreateDirectory(NewAbsoluteFolderPath)) return false;
	
	FString ScreenShotsDir = VictoryPaths__ScreenShotsDir();
	
	**//Find all screenshots**
	TArray<FString> Files;	  //false = not recursive, not expecting subdirectories
	bool Success = GetFiles(ScreenShotsDir, Files, false);
	
	if(!Success)
	{
		return false;
	}
	
	**//Filter**
	TArray<FString> ToRemove; //16 bytes each, more stable than ptrs though since RemoveSwap is involved
	for(FString& Each : Files)
	{
		if(HighResolution)
		{
			//remove those that dont have it
			if(Each.Left(4) != "High")
			{
				ToRemove.Add(Each);
			}
		}
		else
		{ 
			//Remove those that have it!
			if(Each.Left(4) == "High")
			{
				ToRemove.Add(Each);
			}
		}
	}
	
	**//Remove!**
	for(FString& Each : ToRemove)
	{
		Files.RemoveSwap(Each); //Fast remove! Does not preserve order
	}
	
	**//No files?**
	if(Files.Num() < 1)
	{ 
		return false;
	}
	
	**//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Rama's Sort Files by Time Stamp Feature
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//Sort the file names by time stamp
	//  This is my custom c++ struct to do this,
	//  	combined with my operator< and UE4's
	//			TArray::Sort() function!**
	TArray<FFileStampSort> FileSort;
	for(FString& Each : Files)
	{
		FileSort.Add(FFileStampSort(&Each,GetFileTimeStamp(Each)));
		
	}

	//Sort all the file names by their Time Stamp!
	FileSort.Sort();
	
	//Biggest value = last entry
	OriginalFileName = *FileSort.Last().FileName;
	**//~~~~~~~~~~~~~~~~~~~~~~~~~~~~**

	    
	**//Generate new Full File Path!**
	FString NewFullFilePath = NewAbsoluteFolderPath + "/" + NewName + ".bmp";
	
	**//Move File!**
	return RenameFile(NewFullFilePath, ScreenShotsDir + "/" + OriginalFileName);
}



**How It Works**

The core feature of my logic and this node is that I used a custom C++ struct in order to sort all of the files by date!

**I do this in a super-efficient way, using UE4's TArray::Sort function which leverages all of Epic's hard work to create a fast sorting function!**

I defined the C++ **operator&lt;** for my custom struct so that UE4 could do the sorting for me!

**In addition I have developed my own File I/O library since my time in the UE4 Beta program.**

So I had all the supporting functions I needed!

C++ Code Speed

Please note that in my internal file sorting system I do not duplicate the FString data! I refer to it via pointer, and use the FDateTime as the only data I access.

So essentially my custom C++ struct is a FDateTime wrapper for a FString ptr so that UE4 can sort the files for me like Lightning!


**Download and plug in!**

**Latest plugin download is here:**
https://wiki.unrealengine.com/File:VictoryPlugin.zip

Enjoy!

Rama