x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Filtering actors in plugin::StartupModule()

Hi folks

In my plugin I would like to iterate and filter actors in plugin::StartupModule(). Following Rama's example I'm doing this as a simplified test in a vanilla Toolbar Button plugin:

     auto World = GEditor->GetEditorWorldContext().World();
     for (TActorIterator<AStaticMeshActor> ActorItr(World); ActorItr; ++ActorItr)
     {
         AStaticMeshActor* Mesh = *ActorItr;
         UE_LOG(LogTemp, Warning, TEXT("%s"), *ActorItr->GetName())
     }

These lines do exactly what I need if I have them PluginButtonClicked() but for some reason there are no Actors logged if I place the same lines in StartupModule(). I suspect this relates to which context/worlds exists at the time of StartupModule(). My .uplugin has "LoadingPhase": "PostEngineInit" which solved a previous nullptr issue.

I don't want to do this in PluginButtonClicked() because I need a one-time expensive call to the Shotgun api which builds the data-model that drives my menu extenders. StartupModule() seems like the right place but perhaps there is a better option, perhaps something post-load but pre-click.

Any help much appreciated

Mark

Product Version: UE 4.14
Tags:
more ▼

asked Mar 22 '17 at 06:37 PM in C++ Programming

avatar image

Arizona Sky
13 1 4

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

2 answers: sort voted first

PostEngineInit just means the Engine has been initialized, but not that a world has actually been created.

You can see a list of the various phases and their descriptions here.

It's difficult to give you direction as I don't know the requirements for your call. If you just need a valid world, you could look into hooking into something like OnPostWorldInitialization. But if you need to make that call every time someone adds/removes a Static Actor, then maybe doing it in a background or finding some hook for when an object is added to the world (I'm sure there is one - I just can't remember one off the top of my head) would be better.

more ▼

answered Mar 22 '17 at 07:37 PM

avatar image

ExtraLifeMatt
1.4k 31 11 43

avatar image Arizona Sky Mar 22 '17 at 08:31 PM

Thanks Matt, that's exactly what I needed

In StartupModule()

 FWorldDelegates::FWorldInitializationEvent::FDelegate OnWorldCreatedDelegate;
 OnWorldCreatedDelegate = FWorldDelegates::FWorldInitializationEvent::FDelegate::CreateRaw(this, &FMyPlug::OnWorldCreated);
 FDelegateHandle OnWorldCreatedDelegateHandle = FWorldDelegates::OnPostWorldInitialization.Add(OnWorldCreatedDelegate);


With

 void FMyPlug::OnWorldCreated(UWorld* World, const UWorld::InitializationValues IVS) {
 
     for (TActorIterator<AStaticMeshActor> ActorItr(World); ActorItr; ++ActorItr)
     {
         AStaticMeshActor* Mesh = *ActorItr;
         UE_LOG(LogTemp, Warning, TEXT("%s"), *ActorItr->GetName())
     }
 
 }

And the delegate somehow gets and passes the UWorld reference itself so no need for

 auto World = GEditor->GetEditorWorldContext().World();

anymore.

I found a nice usage example here: https://github.com/knepleyp/UTEmotionDetector/blob/master/Source/Private/EmotionDetector.cpp

Funny how once you know the name of the thing you're looking for, it all falls into place. Thanks for your help!

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

There no way to do so from module start up since all modules get loaded before world is initiated. You can detect when world is initiated by binding to this event:

https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/UEngine/OnWorldAdded/index.html

You can also detect world destructions:

https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/UEngine/OnWorldDestroyed/index.html

Keep in mind that in editor it will be triggered multiple times and contain different irreverent worlds, as Editor and PIE world is seperete and all previews are also creating own new world to display things, so use IsGameWorld to detect game world.

https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/UWorld/IsGameWorld/index.html

As i remember PIE world get destroyed once you turn off play mode and new one is created in another rime, this will also happen on level change even in game builds if im not mistaken so prepare your code for world swaps.

more ▼

answered Mar 22 '17 at 07:53 PM

avatar image

Shadowriver
30.6k 907 152 1065

avatar image Arizona Sky Mar 22 '17 at 08:38 PM

Awesome, thanks for the extra links, my solution is above and I'll keep an eye out for world swaps

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question