[Editor Feature Pull Request] Rama's Instanced Static Mesh Editor Feature

Dear Epic and Community,

I’ve made a new editor feature pull request to Epic adds two functions to the engine to:

  1. Take all selected static mesh actors with same static mesh asset, and convert them into an instanced static mesh (ctrl + i)

  2. Reverse the procedure in 1, taking into account whether the original instanced static mesh actor was a Blueprint class.(ctrl + shift + i)

You can view this pull request and add your support here!
https://github.com/EpicGames/UnrealEngine/pull/917


**Result: Easy-To-Use Instanced Static Mesh Actor Editor**


The result is that for a minimal amount of additional code in the Engine, you can now easily edit Instanced Static Mesh Actors in **world space**!

You edit the Instanced Static Mesh as regular static mesh actors, and then merge them together when you are done!

You can go back and edit any particular instance at any time by reverting the instanced static mesh!

Goal Accomplished

I wanted to make it easy for UE4 users to get the performance advantages of Instanced Static Mesh actors while maintaining the convenience of the familiar level editor viewport duplication,rotation,scaling, and translation tools!

I have accomplished this Goal!


**Videos**

**Video 1**

This first video is the plugin version, where I demo the core usefulness.

My fps goes from 9 back to 120 once I convert all the static mesh actors into an instanced static mesh.

I then demonstrate going back in and editing a single instance and then restoring the whole structure to being an instanced static mesh actor again.

*Massive performance gains!*

https://youtube.com/watch?v=iC1sjgalEJg

Video 2 ~ Editor Integration


**Video 3 ~ Blueprint Support!**

https://youtube.com/watch?v=2PPPYl2MC6o


UE4 Editor Undo/Redo

Undo and Redo are fully supported for both creating and reverting the instanced static mesh actor!

I demonstrate this in the second video which is of the Editor-Integration version (this pull request)!



const FScopedTransaction Transaction(LOCTEXT("CreateInstancedStaticMeshFromSelection", "Create Instanced Static Mesh Actor From Selected Actors"));
	
//...

//ISM fully created
NewISM->Modify();



**Versatile Code**

When creating an instanced static mesh actor from a group of selected actors, all the other static meshes that are selected use the static mesh and materials of the "root selected static mesh actor."

But this does not have to be the very first actor in the selection set!

In fact in one of my videos, I accidentally highlight a Directional Light along with all my static mesh actors, and my code still runs just fine!

This is because I simply choose the first found static mesh actor in the selection set as the root.



```


//Root Selected Static Mesh Actor's Component
UStaticMeshComponent* RootSMC = nullptr;

for (FSelectionIterator It(*GEditor->GetSelectedActors()); It; ++It)
{
	AStaticMeshActor* EachSMA = Cast<AStaticMeshActor>( *It );
	if(!EachSMA)
	{
		//Not an SMA
		continue;
	}
		
	//Has root SMC been found yet? (Component of first of selection that is an SMA)
	if(!RootSMC)
	{
		RootSMC = EachSMA->GetStaticMeshComponent();
			
		//Search tags to see if an ISM class was specified
		for(const FName & Each : EachSMA->Tags )
		{


```



Supports Any Number of Materials on Mesh

Please note I am careful to copy all materials during the creation/reverting of the Instanced Static Mesh Actor!



//Materials
const int32 MatTotal = EachISM->GetMesh()->GetNumMaterials();
for(int32 v = 0; v < MatTotal; v++)
{
	Mesh->SetMaterial(v,EachISM->GetMesh()->GetMaterial(v));
}



**BP Support**


My system fully accounts for whether or not the user made a BP out of my new base class, Instanced Static Mesh Actor, and will use that BP class instead!

I do this by adding a tag to the static mesh actors that are created from the BP instanced static mesh actor (when reverting to individual editable meshes).

This tag is serialized of course!

So the user can come back any time and if they take their separate meshes that came from a BP Instanced Static Mesh Actor, they simply press the key to re-create the ISM that comes from their own BP!

This means users can create all manner of Blueprint code for use with the Instanced Static Mesh Editor system that I am presenting to you!



```


//Did the root static mesh actor have an ISM class tag?
TSubclassOf<AInstancedStaticMeshActor> ISMClass = 
	(TagClass && TagClass->IsChildOf(AInstancedStaticMeshActor::StaticClass())) ? TagClass : AInstancedStaticMeshActor::StaticClass() ;
	  
AInstancedStaticMeshActor* NewISM = GetWorld()->SpawnActor<AInstancedStaticMeshActor>(
	ISMClass, 
	RootSMC->GetComponentLocation() , RootSMC->GetComponentRotation(), SpawnInfo 
);


```



Simple Hotkey Key Presses

I simply added two editor hotkeys, CTRL + i and CTRL + SHIFT + i to run the two commands!



void FLevelEditorActionCallbacks::OnCreateInstancedStaticMeshFromSelection()
{
	if(GCurrentLevelEditingViewportClient)
	{
		GCurrentLevelEditingViewportClient->CreateInstancedStaticMeshFromSelection();
	}
} 
void FLevelEditorActionCallbacks::OnRevertInstancedStaticMesh()
{
	if(GCurrentLevelEditingViewportClient)
	{
		GCurrentLevelEditingViewportClient->RevertSelectedInstancedStaticMeshes();
	}
}



**InstancedStaticMeshActor**

Again please note the addition of InstancedStaticMeshActor to the code base, not reflected in the git code changes summary.



```


/**
 * An Instanced Static Mesh Actor renders all instances in a single draw call making it much more efficient
 * than the equivalent number of individual static mesh actors
 *
 * The only restriction is that all instances share the same materials and static mesh asset.
 *
 * @see https://docs.unrealengine.com/latest/INT/Engine/Actors/InstancedStaticMeshActor/
 * @see UInstancedStaticMeshComponent
 */ 
UCLASS(hidecategories=(Input), showcategories=("Input|MouseInput", "Input|TouchInput"), ConversionRoot, ComponentWrapperClass, meta=(ChildCanTick))
class ENGINE_API AInstancedStaticMeshActor : public AActor
{
	GENERATED_UCLASS_BODY()
private_subobject:
	UPROPERTY(Category = InstancedStaticMeshActor, VisibleAnywhere, BlueprintReadOnly, meta = (ExposeFunctionCategories = "Mesh,Rendering,Physics,Components|StaticMesh,Components|InstancedStaticMesh", AllowPrivateAccess = "true"))
	UInstancedStaticMeshComponent* Mesh; 
	
public:
	/** Returns InstancedStaticMeshComponent subobject **/
	class UInstancedStaticMeshComponent* GetMesh() const;
	
};


```



Conclusion

So there you have it!

With only a minimal amount of code I am enabling everyone to edit Instanced Static Mesh actors in world space using all the familiar tools used during normal level editing!

And also supporting Blueprint-based custom Instanced Static Mesh Actor classes!

My gift to you, the Community and Epic!

Enjoy!

[FONT=Comic Sans MS]:heart:

Rama

PS: If you like this pull request please support it on Github itself!
https://github.com/EpicGames/UnrealEngine/pull/917

This is one of my favorite additions Rama. I had an issue building large cave systems but now creating large worlds will not be an issue.

Thanks Rama,

Isaac

PS Sent my support on github

Amazing! thank you

Wow. That’s outstanding work Rama. Thank you for sharing it with the community! Cheers,

J^2

The Birth of Instanced Static Mesh Creator

Dear Community and Epic,

After feedback from Matt from Epic, I have re-written my offering to follow his suggestions.

He recommended creating a separate name space and so I created a static class called FInstancedStaticMeshCreator.

More functionality can be added to this utility class in the future!

Currently it can create a new instanced static mesh actor from a source static mesh component, and a series of instance transforms.

The other functions in the new class respond to the level editor hotkeys/callbacks to perform the actions that you see in my videos in the original post!

All functionality shown in the videos remains the same, and now UE4 has a new utility class: Instanced Static Mesh Creator!

More Info and the C++ Code
https://github.com/EpicGames/UnrealEngine/pull/917


**How To Use It**

Here's a pic of the default level viewport hot keys, I use this key presses in the videos above!

(right click-&gt;new tab to see image in higher res)
![9358b0c39685fb5548273cf047af9ac4a08f26cc.jpeg|1280x960](upload://l1ucOkHSm7BaK8aXBH9r9ME51zS.jpeg)

:)

Rama

What a great addition EverNewJoy aka Rama

https://assets-cdn.github.com/images/icons/emoji/unicode/1f44d.png

Your devotion to the UE4 Community is unquestionable and outstanding

https://assets-cdn.github.com/images/icons/emoji/unicode/1f4af.png

Looks great Rama! Is it possible for this system to also work at runtime? It doesn’t seem like it but would be great if you could!

Yes this is possible, especially the revised engine code that I have now submitted which simply spawns an empty actor and adds an instanced static mesh component to it, as per Epic Matt’s request!

The reason this is an editor integration is so that instanced static mesh actors can be created, edited, and recreated in the level viewport itself, as shown in my 3 videos in first post.

With the simple press of CTRL + i, or CTRL + SHIFT + i, you can make all selected static mesh actors into a single instanced static mesh, or break an instanced static mesh back into individual editable actors!

:slight_smile:

Rama

Update to Engine Integration

I just added support for layers and world outliner folder paths!

Git Commit
https://github.com/EverNewJoy/UnrealEngine/commit/7b145be43868ff6156a6cdb144115bfe044ab985

Now if you revert an instanced static mesh you played into a folder, all the new static mesh actors will be added to the same folder!

And all layer information is copied as well!

This works both ways, so if you had a bunch of static mesh actors in a layer, and turn them into a single instanced static mesh actor, that actor will have all the layers and be in the folder of the root static mesh actor from the original selection.

Enjoy!

Rama

Github Accident

I accidentally referenced every single person in the UE4 Git community when I was trying to write “@everyone” to thank several people at once for their supportive comments about this editor feature pull request.

Git presented me with the option of @UnrealEngineDevs and I was like “okay sure”

And this proceeded to add more than 300,000 people to my pull request email notify list!

I apologize to everyone who got unwanted emails! It was not my intention to disturb anyone!

!

!

So I accidentally nuked my pull request, because Epic and I could not figure out how to stop everyone in the known UE4 Git universe from getting updates about my PR

Thank you for all your lovely feedback,

I will be re-submitting the pull request soon!

[FONT=Comic Sans MS]:heart:

Rama

PS: if you think this is funny its okay to laugh!

I am never writing @everyone in git pull requests ever again :slight_smile:

New Pull Request Is Live

I have re-submitted my Instanced Static Mesh Editor pull request here!

If you’d like to see this integrated into the engine you can add your support here on github!

New Github Pull Request
https://github.com/EpicGames/UnrealEngine/pull/917

Rama

Whoops! :smiley: hahaha!! Nevermind…Great work btw! :slight_smile:

Hee hee!

**Thanks!
**
:heart:

Rama

PS:

Again for new viewers, you can see my new and active pull request here:
https://github.com/EpicGames/UnrealEngine/pull/917

Hey Rama - What you are doing is really awesome!

Cannot wait to see this put into the main unreal engine branch :slight_smile:

Look at it this way, at least it was an AWESOME Pull Request and not something either private (never meant to be submitted) or a pretty small 1 line of code improvement type Pull Request :wink:

P.S. As an added bonus, everyone that has been living under a rock and doesn’t know who you are and what you’ve contributed to this great community now knows :wink:

Very cool stuff, Rama! I actually did something similar using blueprints a couple of months ago. I found it absolutely necessary for maintaining good performance when creating large tile-based maps. My solution works by making the static mesh Components of actors invisible and placing instanced static meshes tied to a single actor. The performance gains are similar to what I’m seeing in your solution, though it is clunkier that your solution, and has a few limitations. I’m hoping your additions will be added as defaults in the engine soon. Here’s a video of my own solution:

https://youtube.com/watch?v=1eR9o44HL6Q

Edit: By the way, I’m getting a 404 error when I try to access the link you gave to the new pull request.

Rama FTW! As always, great work buddy! :slight_smile:

Did you link your Git account with your Unreal Engine account?

Maybe not. If the link is working for the rest of you that’s probably the reason.

Astonishing!
Well done!
Excellent!
Superb!
Oh my god!
Marvellous!
Elegant!

Please integrate this. :wink:

@Monokkel

Great work making your own solution, and I like your color choice!

:slight_smile:

Hee hee!

Great to hear from your RyanJon!

Thanks! Hee hee!

:heart:

Rama