// Moves the contents of all of the children graphs (recursively) into the target graph. This does not clone, it's destructive to the source void FEdGraphUtilities::MergeChildrenGraphsIn(UEdGraph* MergeTarget, UEdGraph* ParentGraph, bool bRequireSchemaMatch, bool bInIsCompiling/* = false*/) { // Determine if we are regenerating a blueprint on load UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraph(MergeTarget); const bool bIsLoading = Blueprint ? Blueprint->bIsRegeneratingOnLoad : false; // Merge all children nodes in too for (int32 Index = 0; Index < ParentGraph->SubGraphs.Num(); ++Index) { UEdGraph* ChildGraph = ParentGraph->SubGraphs[Index]; auto NodeOwner = Cast<const UEdGraphNode>(ChildGraph ? ChildGraph->GetOuter() : nullptr); const bool bNonVirtualGraph = NodeOwner ? NodeOwner->ShouldMergeChildGraphs() : true; // Only merge children in with the same schema as the parent auto ChildSchema = ChildGraph ? ChildGraph->GetSchema() : nullptr; auto TargetSchema = MergeTarget ? MergeTarget->GetSchema() : nullptr; const bool bSchemaMatches = ChildSchema && TargetSchema && ChildSchema->GetClass()->IsChildOf(TargetSchema->GetClass()); const bool bDoMerge = bNonVirtualGraph && (!bRequireSchemaMatch || bSchemaMatches); if (bDoMerge) { // Even if we don't require a match to recurse, we do to actually copy the nodes if (bSchemaMatches) { ChildGraph->MoveNodesToAnotherGraph(MergeTarget, IsAsyncLoading() || bIsLoading, bInIsCompiling); } MergeChildrenGraphsIn(MergeTarget, ChildGraph, bRequireSchemaMatch, bInIsCompiling); } } }
void USoundNodeModPlayer::LoadAsset() { if (IsAsyncLoading()) { SoundMod = SoundModAssetPtr.Get(); if (SoundMod == nullptr) { LoadPackageAsync(SoundModAssetPtr.GetLongPackageName(), FLoadPackageAsyncDelegate::CreateUObject(this, &USoundNodeModPlayer::OnSoundModLoaded)); } } else { SoundMod = SoundModAssetPtr.LoadSynchronous(); } }
void USoundNodeWavePlayer::LoadAsset() { if (IsAsyncLoading()) { SoundWave = SoundWaveAssetPtr.Get(); if (SoundWave == nullptr) { const FString LongPackageName = SoundWaveAssetPtr.GetLongPackageName(); if (!LongPackageName.IsEmpty()) { LoadPackageAsync(LongPackageName, FLoadPackageAsyncDelegate::CreateUObject(this, &USoundNodeWavePlayer::OnSoundWaveLoaded)); } } } else { SoundWave = SoundWaveAssetPtr.LoadSynchronous(); } }
// Clones the content from SourceGraph and merges it into MergeTarget; including merging/flattening all of the children from the SourceGraph into MergeTarget void FEdGraphUtilities::CloneAndMergeGraphIn(UEdGraph* MergeTarget, UEdGraph* SourceGraph, FCompilerResultsLog& MessageLog, bool bRequireSchemaMatch, bool bInIsCompiling/* = false*/, TArray<UEdGraphNode*>* OutClonedNodes) { // Clone the graph, then move all of it's children UEdGraph* ClonedGraph = CloneGraph(SourceGraph, NULL, &MessageLog, true); MergeChildrenGraphsIn(ClonedGraph, ClonedGraph, bRequireSchemaMatch); // Duplicate the list of cloned nodes if (OutClonedNodes != NULL) { OutClonedNodes->Append(ClonedGraph->Nodes); } // Determine if we are regenerating a blueprint on load UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraph(MergeTarget); const bool bIsLoading = Blueprint ? Blueprint->bIsRegeneratingOnLoad : false; // Move them all to the destination ClonedGraph->MoveNodesToAnotherGraph(MergeTarget, IsAsyncLoading() || bIsLoading, bInIsCompiling); }
bool UUpdateManager::Tick(float InDeltaTime) { if (CurrentUpdateState == EUpdateState::WaitingOnInitialLoad) { WorstNumFilesPendingLoadViewed = FMath::Max(GetNumAsyncPackages(), WorstNumFilesPendingLoadViewed); //UE_LOG(LogInit, Log, TEXT("Load progress %f (%d %d)"), GetLoadProgress(), GetNumAsyncPackages(), WorstNumFilesPendingLoadViewed); if (!IsAsyncLoading()) { const double LoadTime = FPlatformTime::Seconds() - LoadStartTime; UE_LOG(LogHotfixManager, Log, TEXT("Finished initial load/hotfix phase in %fs"), LoadTime); ACCUM_LOADTIME(TEXT("FinishedInitialLoadHotfix"), LoadTime); InitialPreloadComplete(); TickerHandle.Reset(); return false; } } return true; }
void UWorld::LoadSecondaryLevels(bool bForce, TSet<FString>* CookedPackages) { check( GIsEditor ); // streamingServer // Only load secondary levels in the Editor, and not for commandlets. if( (!IsRunningCommandlet() || bForce) // Don't do any work for world info actors that are part of secondary levels being streamed in! && !IsAsyncLoading()) { for( int32 LevelIndex=0; LevelIndex<StreamingLevels.Num(); LevelIndex++ ) { ULevelStreaming* const StreamingLevel = StreamingLevels[LevelIndex]; if( StreamingLevel ) { bool bAlreadyCooked = false; // If we are cooking don't cook sub levels multiple times if they've already been cooked FString PackageFilename; const FString StreamingLevelWorldAssetPackageName = StreamingLevel->GetWorldAssetPackageName(); if (CookedPackages) { if (FPackageName::DoesPackageExist(StreamingLevelWorldAssetPackageName, NULL, &PackageFilename)) { PackageFilename = FPaths::ConvertRelativePathToFull(PackageFilename); bAlreadyCooked |= CookedPackages->Contains( PackageFilename ); } } bool bAlreadyLoaded = false; UPackage* LevelPackage = FindObject<UPackage>(NULL, *StreamingLevelWorldAssetPackageName,true); // don't need to do any extra work if the level is already loaded if ( LevelPackage && LevelPackage->IsFullyLoaded() ) { bAlreadyLoaded = true; } if ( !bAlreadyCooked && !bAlreadyLoaded ) { bool bLoadedLevelPackage = false; const FName StreamingLevelWorldAssetPackageFName = StreamingLevel->GetWorldAssetPackageFName(); // Load the package and find the world object. if( FPackageName::IsShortPackageName(StreamingLevelWorldAssetPackageFName) == false ) { ULevel::StreamedLevelsOwningWorld.Add(StreamingLevelWorldAssetPackageFName, this); LevelPackage = LoadPackage( NULL, *StreamingLevelWorldAssetPackageName, LOAD_None ); ULevel::StreamedLevelsOwningWorld.Remove(StreamingLevelWorldAssetPackageFName); if( LevelPackage ) { bLoadedLevelPackage = true; // Find the world object in the loaded package. UWorld* LoadedWorld = UWorld::FindWorldInPackage(LevelPackage); // If the world was not found, it could be a redirector to a world. If so, follow it to the destination world. if (!LoadedWorld) { LoadedWorld = UWorld::FollowWorldRedirectorInPackage(LevelPackage); } check(LoadedWorld); if ( !LevelPackage->IsFullyLoaded() ) { // LoadedWorld won't be serialized as there's a BeginLoad on the stack so we manually serialize it here. check( LoadedWorld->GetLinker() ); LoadedWorld->GetLinker()->Preload( LoadedWorld ); } // Keep reference to prevent garbage collection. check( LoadedWorld->PersistentLevel ); ULevel* NewLoadedLevel = LoadedWorld->PersistentLevel; NewLoadedLevel->OwningWorld = this; StreamingLevel->SetLoadedLevel(NewLoadedLevel); } } else { UE_LOG(LogSpawn, Warning, TEXT("Streaming level uses short package name (%s). Level will not be loaded."), *StreamingLevelWorldAssetPackageName); } // Remove this level object if the file couldn't be found. if ( !bLoadedLevelPackage ) { StreamingLevels.RemoveAt( LevelIndex-- ); MarkPackageDirty(); } } } } } }
void UGameEngine::Tick( float DeltaSeconds, bool bIdleMode ) { SCOPE_CYCLE_COUNTER(STAT_GameEngineTick); NETWORK_PROFILER(GNetworkProfiler.TrackFrameBegin()); int32 LocalTickCycles=0; CLOCK_CYCLES(LocalTickCycles); // ----------------------------------------------------- // Non-World related stuff // ----------------------------------------------------- if( DeltaSeconds < 0.0f ) { #if (UE_BUILD_SHIPPING && WITH_EDITOR) // End users don't have access to the secure parts of UDN. Regardless, they won't // need the warning because the game ships with AMD drivers that address the issue. UE_LOG(LogEngine, Fatal,TEXT("Negative delta time!")); #else // Send developers to the support list thread. UE_LOG(LogEngine, Fatal,TEXT("Negative delta time! Please see https://udn.epicgames.com/lists/showpost.php?list=ue3bugs&id=4364")); #endif } // Tick allocator if( GMalloc != NULL ) { GMalloc->Tick( DeltaSeconds ); } // Tick the module manager FModuleManager::Get().Tick(); if (!IsRunningDedicatedServer() && !IsRunningCommandlet()) { // Clean up the game viewports that have been closed. CleanupGameViewport(); } // If all viewports closed, time to exit. if(GIsClient && GameViewport == NULL ) { UE_LOG(LogEngine, Log, TEXT("All Windows Closed") ); FPlatformMisc::RequestExit( 0 ); return; } if ( GameViewport != NULL ) { // Decide whether to drop high detail because of frame rate. GameViewport->SetDropDetail(DeltaSeconds); } // Update subsystems. { // This assumes that UObject::StaticTick only calls ProcessAsyncLoading. StaticTick( DeltaSeconds ); } // ----------------------------------------------------- // Begin ticking worlds // ----------------------------------------------------- int32 OriginalGWorldContext = INDEX_NONE; for (int32 i=0; i < WorldList.Num(); ++i) { if (WorldList[i].World() == GWorld) { OriginalGWorldContext = WorldList[i].ContextHandle; break; } } bool WorldWasPaused = false; for (int32 WorldIdx = 0; WorldIdx < WorldList.Num(); ++WorldIdx) { FWorldContext &Context = WorldList[WorldIdx]; if (Context.World() == NULL) { continue; } WorldWasPaused |= Context.World()->IsPaused(); GWorld = Context.World(); // Tick all travel and Pending NetGames (Seamless, server, client) TickWorldTravel(Context, DeltaSeconds); if (!IsRunningDedicatedServer() && !IsRunningCommandlet()) { // Only update reflection captures in game once all 'always loaded' levels have been loaded // This won't work with actual level streaming though if (Context.World()->AreAlwaysLoadedLevelsLoaded()) { // Update sky light first because it's considered direct lighting, sky diffuse will be visible in reflection capture indirect specular USkyLightComponent::UpdateSkyCaptureContents(Context.World()); UReflectionCaptureComponent::UpdateReflectionCaptureContents(Context.World()); } } if (!bIdleMode) { // Tick the world. GameCycles=0; CLOCK_CYCLES(GameCycles); Context.World()->Tick( LEVELTICK_All, DeltaSeconds ); UNCLOCK_CYCLES(GameCycles); } // Issue cause event after first tick to provide a chance for the game to spawn the player and such. if( Context.World()->bWorldWasLoadedThisTick ) { Context.World()->bWorldWasLoadedThisTick = false; const TCHAR* InitialExec = Context.LastURL.GetOption(TEXT("causeevent="),NULL); ULocalPlayer* GamePlayer = Context.GamePlayers.Num() > 0 ? Context.GamePlayers[0] : NULL; if( InitialExec && GamePlayer ) { UE_LOG(LogEngine, Log, TEXT("Issuing initial cause event passed from URL: %s"), InitialExec); GamePlayer->Exec( GamePlayer->GetWorld(), *(FString("CAUSEEVENT ") + InitialExec), *GLog ); } Context.World()->bTriggerPostLoadMap = true; } // Tick the viewports. if ( GameViewport != NULL && !bIdleMode ) { SCOPE_CYCLE_COUNTER(STAT_GameViewportTick); GameViewport->Tick(DeltaSeconds); } UpdateTransitionType(Context.World()); // fixme: this will only happen once due to the static bool, but still need to figure out how to handle this for multiple worlds if (FPlatformProperties::SupportsWindowedMode()) { // Hide the splashscreen and show the game window static bool bFirstTime = true; if ( bFirstTime ) { bFirstTime = false; FPlatformSplash::Hide(); if ( GameViewportWindow.IsValid() ) { GameViewportWindow.Pin()->ShowWindow(); FSlateApplication::Get().RegisterGameViewport( GameViewportWidget.ToSharedRef() ); } } } if (!bIdleMode && !IsRunningDedicatedServer() && !IsRunningCommandlet()) { // Render everything. RedrawViewports(); } // Block on async loading if requested. if( Context.World()->bRequestedBlockOnAsyncLoading ) { // Only perform work if there is anything to do. This ensures we are not syncronizing with the GPU // and suspending the device needlessly. bool bWorkToDo = IsAsyncLoading(); if (!bWorkToDo) { Context.World()->UpdateLevelStreaming(); bWorkToDo = Context.World()->IsVisibilityRequestPending(); } if (bWorkToDo) { // tell clients to do the same so they don't fall behind for( FConstPlayerControllerIterator Iterator = Context.World()->GetPlayerControllerIterator(); Iterator; ++Iterator ) { APlayerController* PlayerController = *Iterator; UNetConnection* Conn = Cast<UNetConnection>(PlayerController->Player); if (Conn != NULL && Conn->GetUChildConnection() == NULL) { // call the event to replicate the call PlayerController->ClientSetBlockOnAsyncLoading(); // flush the connection to make sure it gets sent immediately Conn->FlushNet(true); } } FStreamingPause::GameThreadWantsToSuspendRendering( GameViewport ? GameViewport->Viewport : NULL ); // Flushes level streaming requests, blocking till completion. Context.World()->FlushLevelStreaming(); FStreamingPause::GameThreadWantsToResumeRendering(); } Context.World()->bRequestedBlockOnAsyncLoading = false; } // streamingServer if( GIsServer == true ) { SCOPE_CYCLE_COUNTER(STAT_UpdateLevelStreaming); Context.World()->UpdateLevelStreaming(); } // Update Audio. This needs to occur after rendering as the rendering code updates the listener position. if( GetAudioDevice() ) { GetAudioDevice()->Update( !Context.World()->IsPaused() ); } if( GIsClient ) { // GStreamingManager is updated outside of a world context. For now, assuming it needs to tick here, before possibly calling PostLoadMap. // Will need to take another look when trying to support multiple worlds. // Update resource streaming after viewports have had a chance to update view information. Normal update. GStreamingManager->Tick( DeltaSeconds ); if ( Context.World()->bTriggerPostLoadMap ) { Context.World()->bTriggerPostLoadMap = false; // Turns off the loading movie (if it was turned on by LoadMap) and other post-load cleanup. PostLoadMap(); } } UNCLOCK_CYCLES(LocalTickCycles); TickCycles=LocalTickCycles; // See whether any map changes are pending and we requested them to be committed. ConditionalCommitMapChange(Context); } // ---------------------------- // End per-world ticking // ---------------------------- // Restore original GWorld*. This will go away one day. if (OriginalGWorldContext != INDEX_NONE) { GWorld = WorldContextFromHandle(OriginalGWorldContext).World(); } // tell renderer about GWorld->IsPaused(), before rendering { ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER( SetPaused, bool, bGamePaused, WorldWasPaused, { GRenderingRealtimeClock.SetGamePaused(bGamePaused); }); }