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

, how do you get working in packaged games? When I try running a packaged game’s .exe, I get the error message "Plugin ‘VictoryPlugin’ failed to load because module ‘VictoryBPLibrary’ could not be found. Going by thread (Plugins Are Only Working For People in a Package Game if they have C++ Project - C++ - Epic Developer Community Forums) I get the impression the source code needs to be compiled into the project, though I haven’t tried that yet.

Please make a pull request for your “Set Viewport Mouse Position” Nodes :slight_smile:

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 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 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 and you can ping Victory Image Loader to to ask it if it has finished loading everything.

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

:slight_smile:

Hey ! 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 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 will be the next thing I work on in my spare, buuuuut check out my next poooost!

Load Image From File, and Retrieve Pixel Data!

Dear Community,

As requested I’ve made a node that let’s you load an image from file, and get 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!!

** 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!

♥

You truly are an unstoppable coding machine, . Thank you! Can’t wait to try out. Is 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 **
https://wiki.unrealengine.com/File:VictoryPlugin.zip

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

♥

I am going to have to see if I can get an Earth map generated using 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 ! used your ISM today and worked amazingly well.

, 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 on plugin!

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:

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 on that same mesh.

, I love you. :slight_smile:

J^2

It lives! :slight_smile:


Source File:


, 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

Wooohoo!

Awesome !

Thanks for sharing the pics!

Your procedural map looks wonderful!

:slight_smile:

Hi !
You already know how we love your plugin, so let’s go with the requests! :wink:
A nice 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