Exemplo n.º 1
3
bool UClassThumbnailRenderer::CanVisualizeAsset(UObject* Object)
{
	if (ThumbnailScene == nullptr)
	{
		ThumbnailScene = new FClassThumbnailScene();
	}

	UClass* Class = Cast<UClass>(Object);

	// Only visualize actor based classes
	if (Class && Class->IsChildOf(AActor::StaticClass()))
	{
		// Try to find any visible primitive components in the class' CDO
		AActor* CDO = Class->GetDefaultObject<AActor>();

		TInlineComponentArray<UActorComponent*> Components;
		CDO->GetComponents(Components);

		for (auto CompIt = Components.CreateConstIterator(); CompIt; ++CompIt)
		{
			if (ThumbnailScene->IsValidComponentForVisualization(*CompIt))
			{
				return true;
			}
		}
	}

	return false;
}
void UActorRecording::StartRecordingNewComponents(ULevelSequence* CurrentSequence, float CurrentSequenceTime)
{
	if (GetActorToRecord() != nullptr)
	{
		// find the new component(s)
		TInlineComponentArray<USceneComponent*> NewComponents;
		TArray<USceneComponent*> SceneComponents;
		GetSceneComponents(SceneComponents);
		for(USceneComponent* SceneComponent : SceneComponents)
		{
			if(ValidComponent(SceneComponent))
			{
				TWeakObjectPtr<USceneComponent> WeakSceneComponent(SceneComponent);
				int32 FoundIndex = TrackedComponents.Find(WeakSceneComponent);
				if(FoundIndex == INDEX_NONE)
				{
					// new component!
					NewComponents.Add(SceneComponent);
				}
			}
		}

		ProcessNewComponentArray(NewComponents);

		UMovieScene* MovieScene = CurrentSequence->GetMovieScene();
		check(MovieScene);

		FAnimationRecordingSettings ComponentAnimationSettings = AnimationSettings;
		ComponentAnimationSettings.bRemoveRootAnimation = false;
		ComponentAnimationSettings.bRecordInWorldSpace = false;

		const USequenceRecorderSettings* Settings = GetDefault<USequenceRecorderSettings>();
		if (!bRecordToPossessable)
		{
			FMovieSceneSpawnable* Spawnable = MovieScene->FindSpawnable(Guid);
			check(Spawnable);

			AActor* ObjectTemplate = CastChecked<AActor>(Spawnable->GetObjectTemplate());

			for (USceneComponent* SceneComponent : NewComponents)
			{
				// new component, so we need to add this to our BP if it didn't come from SCS
				FName NewName;
				if (SceneComponent->CreationMethod != EComponentCreationMethod::SimpleConstructionScript)
				{
					// Give this component a unique name within its parent
					NewName = *FString::Printf(TEXT("Dynamic%s"), *SceneComponent->GetFName().GetPlainNameString());
					NewName.SetNumber(1);
					while (FindObjectFast<UObject>(ObjectTemplate, NewName))
					{
						NewName.SetNumber(NewName.GetNumber() + 1);
					}

					USceneComponent* TemplateRoot = ObjectTemplate->GetRootComponent();
					USceneComponent* AttachToComponent = nullptr;

					// look for a similar attach parent in the current structure
					USceneComponent* AttachParent = SceneComponent->GetAttachParent();
					if(AttachParent != nullptr)
					{
						// First off, check if we're attached to a component that has already been duplicated into this object
						// If so, the name lookup will fail, so we use a direct reference
						if (TWeakObjectPtr<USceneComponent>* DuplicatedComponent = DuplicatedDynamicComponents.Find(AttachParent))
						{
							AttachToComponent = DuplicatedComponent->Get();
						}
					
						// If we don't have an attachment parent duplicated already, perform a name lookup
						if (!AttachToComponent)
						{
							FName AttachName = SceneComponent->GetAttachParent()->GetFName();

							TInlineComponentArray<USceneComponent*> AllChildren;
							ObjectTemplate->GetComponents(AllChildren);

							for (USceneComponent* Child : AllChildren)
							{
								CA_SUPPRESS(28182); // Dereferencing NULL pointer. 'Child' contains the same NULL value as 'AttachToComponent' did.
								if (Child->GetFName() == AttachName)
								{
									AttachToComponent = Child;
									break;
								}
							}
						}
					}

					if (!AttachToComponent)
					{
						AttachToComponent = ObjectTemplate->GetRootComponent();
					}

					USceneComponent* NewTemplateComponent = Cast<USceneComponent>(StaticDuplicateObject(SceneComponent, ObjectTemplate, NewName, RF_AllFlags & ~RF_Transient));
					NewTemplateComponent->AttachToComponent(AttachToComponent, FAttachmentTransformRules::KeepRelativeTransform, SceneComponent->GetAttachSocketName());

					ObjectTemplate->AddInstanceComponent(NewTemplateComponent);

					DuplicatedDynamicComponents.Add(SceneComponent, NewTemplateComponent);
				}
				else
				{
					NewName = SceneComponent->GetFName();
				}

				StartRecordingComponentProperties(NewName, SceneComponent, GetActorToRecord(), CurrentSequence, CurrentSequenceTime, ComponentAnimationSettings);

				bNewComponentAddedWhileRecording = true;
			}

			SyncTrackedComponents();
		}
		else
		{
			for (USceneComponent* SceneComponent : NewComponents)
			{
				// new component, start recording
				StartRecordingComponentProperties(SceneComponent->GetFName(), SceneComponent, GetActorToRecord(), CurrentSequence, CurrentSequenceTime, ComponentAnimationSettings);
			}

			SyncTrackedComponents();
		}
	}
}
Exemplo n.º 3
1
void UUnrealEdEngine::DrawComponentVisualizersHUD(const FViewport* Viewport, const FSceneView* View, FCanvas* Canvas)
{
	// Iterate over all selected actors
	for (FSelectionIterator It(GetSelectedActorIterator()); It; ++It)
	{
		AActor* Actor = Cast<AActor>(*It);
		if (Actor != NULL)
		{
			// Then iterate over components of that actor
			TInlineComponentArray<UActorComponent*> Components;
			Actor->GetComponents(Components);

			for (int32 CompIdx = 0; CompIdx<Components.Num(); CompIdx++)
			{
				UActorComponent* Comp = Components[CompIdx];
				if (Comp->IsRegistered())
				{
					// Try and find a visualizer

					TSharedPtr<FComponentVisualizer> Visualizer = FindComponentVisualizer(Comp->GetClass());
					if (Visualizer.IsValid())
					{
						Visualizer->DrawVisualizationHUD(Comp, Viewport, View, Canvas);
					}
				}
			}
		}
	}
}
Exemplo n.º 4
1
USkeleton* FAnimationTrackEditor::AcquireSkeletonFromObjectGuid(const FGuid& Guid)
{
	TArray<UObject*> OutObjects;
	GetSequencer()->GetRuntimeObjects(GetSequencer()->GetFocusedMovieSceneInstance(), Guid, OutObjects);

	USkeleton* Skeleton = NULL;
	for (int32 i = 0; i < OutObjects.Num(); ++i)
	{
		AActor* Actor = Cast<AActor>(OutObjects[i]);

		if (Actor != NULL)
		{
			TInlineComponentArray<USkeletalMeshComponent*> SkeletalMeshComponents;
			Actor->GetComponents(SkeletalMeshComponents);

			for (int32 j = 0; j <SkeletalMeshComponents.Num(); ++j)
			{
				USkeletalMeshComponent* SkeletalMeshComp = SkeletalMeshComponents[j];
				if (SkeletalMeshComp->SkeletalMesh && SkeletalMeshComp->SkeletalMesh->Skeleton)
				{
					// @todo Multiple actors, multiple components
					check(!Skeleton);
					Skeleton = SkeletalMeshComp->SkeletalMesh->Skeleton;
				}
			}
		}
	}

	return Skeleton;
}
Exemplo n.º 5
0
//* Destroys the constructed components.
void AActor::DestroyConstructedComponents()
{
	// Remove all existing components
	TInlineComponentArray<UActorComponent*> PreviouslyAttachedComponents;
	GetComponents(PreviouslyAttachedComponents);

	// We need the hierarchy to be torn down in attachment order, so do a quick sort
	PreviouslyAttachedComponents.Remove(nullptr);
	PreviouslyAttachedComponents.Sort([](UActorComponent& A, UActorComponent& B)
	{
		if (USceneComponent* BSC = Cast<USceneComponent>(&B))
		{
			if (BSC->AttachParent == &A)
			{
				return false;
			}
		}
		return true;
	});

	for (UActorComponent* Component : PreviouslyAttachedComponents)
	{
		if (Component)
		{
			bool bDestroyComponent = false;
			if (Component->IsCreatedByConstructionScript())
			{
				bDestroyComponent = true;
			}
			else
			{
				UActorComponent* OuterComponent = Component->GetTypedOuter<UActorComponent>();
				while (OuterComponent)
				{
					if (OuterComponent->IsCreatedByConstructionScript())
					{
						bDestroyComponent = true;
						break;
					}
					OuterComponent = OuterComponent->GetTypedOuter<UActorComponent>();
				}
			}

			if (bDestroyComponent)
			{
				if (Component == RootComponent)
				{
					RootComponent = NULL;
				}

				Component->DestroyComponent();

				// Rename component to avoid naming conflicts in the case where we rerun the SCS and name the new components the same way.
				FName const NewBaseName( *(FString::Printf(TEXT("TRASH_%s"), *Component->GetClass()->GetName())) );
				FName const NewObjectName = MakeUniqueObjectName(this, GetClass(), NewBaseName);
				Component->Rename(*NewObjectName.ToString(), this, REN_ForceNoResetLoaders|REN_DontCreateRedirectors|REN_NonTransactional);
			}
		}
	}
}
Exemplo n.º 6
0
void UUnrealEdEngine::SetActorSelectionFlags (AActor* InActor)
{
	TInlineComponentArray<UActorComponent*> Components;
	InActor->GetComponents(Components);

	//for every component in the actor
	for(int32 ComponentIndex = 0; ComponentIndex < Components.Num(); ComponentIndex++)
	{
		UActorComponent* Component = Components[ComponentIndex];
		if (Component->IsRegistered())
		{
			// If we have a 'child actor' component, want to update its visible selection state
			UChildActorComponent* ChildActorComponent = Cast<UChildActorComponent>(Component);
			if(ChildActorComponent != NULL && ChildActorComponent->ChildActor != NULL)
			{
				SetActorSelectionFlags(ChildActorComponent->ChildActor);
			}

			UPrimitiveComponent* PrimComponent = Cast<UPrimitiveComponent>(Component);
			if(PrimComponent != NULL && PrimComponent->IsRegistered())
			{
				PrimComponent->PushSelectionToProxy();
			}

			UDecalComponent* DecalComponent = Cast<UDecalComponent>(Component);
			if(DecalComponent != NULL)// && DecalComponent->IsRegistered())
			{
				DecalComponent->PushSelectionToProxy();
			}
		}
	}
}
Exemplo n.º 7
0
void AActor::CheckForErrors()
{
	if ( GetClass()->HasAnyClassFlags(CLASS_Deprecated) )
	{
		FFormatNamedArguments Arguments;
		Arguments.Add(TEXT("ActorName"), FText::FromString(GetName()));
		FMessageLog("MapCheck").Warning()
			->AddToken(FUObjectToken::Create(this))
			->AddToken(FTextToken::Create(FText::Format(LOCTEXT( "MapCheck_Message_ActorIsObselete_Deprecated", "{ActorName} : Obsolete and must be removed! (Class is deprecated)" ), Arguments) ))
			->AddToken(FMapErrorToken::Create(FMapErrors::ActorIsObselete));
		return;
	}
	if ( GetClass()->HasAnyClassFlags(CLASS_Abstract) )
	{
		FFormatNamedArguments Arguments;
		Arguments.Add(TEXT("ActorName"), FText::FromString(GetName()));
		FMessageLog("MapCheck").Warning()
			->AddToken(FUObjectToken::Create(this))
			->AddToken(FTextToken::Create(FText::Format(LOCTEXT( "MapCheck_Message_ActorIsObselete_Abstract", "{ActorName} : Obsolete and must be removed! (Class is abstract)" ), Arguments) ))
			->AddToken(FMapErrorToken::Create(FMapErrors::ActorIsObselete));
		return;
	}

	UPrimitiveComponent* PrimComp = Cast<UPrimitiveComponent>(RootComponent);
	if( PrimComp && (PrimComp->Mobility != EComponentMobility::Movable) && PrimComp->BodyInstance.bSimulatePhysics)
	{
		FFormatNamedArguments Arguments;
		Arguments.Add(TEXT("ActorName"), FText::FromString(GetName()));
		FMessageLog("MapCheck").Warning()
			->AddToken(FUObjectToken::Create(this))
			->AddToken(FTextToken::Create(FText::Format(LOCTEXT( "MapCheck_Message_StaticPhysNone", "{ActorName} : Static object with bSimulatePhysics set to true" ), Arguments) ))
			->AddToken(FMapErrorToken::Create(FMapErrors::StaticPhysNone));
	}

	if( RootComponent && FMath::IsNearlyZero( GetRootComponent()->RelativeScale3D.X * GetRootComponent()->RelativeScale3D.Y * GetRootComponent()->RelativeScale3D.Z ) )
	{
		FFormatNamedArguments Arguments;
		Arguments.Add(TEXT("ActorName"), FText::FromString(GetName()));
		FMessageLog("MapCheck").Error()
			->AddToken(FUObjectToken::Create(this))
			->AddToken(FTextToken::Create(FText::Format(LOCTEXT( "MapCheck_Message_InvalidDrawscale", "{ActorName} : Invalid DrawScale/DrawScale3D" ), Arguments) ))
			->AddToken(FMapErrorToken::Create(FMapErrors::InvalidDrawscale));
	}

	// Route error checking to components.
	TInlineComponentArray<UActorComponent*> Components;
	GetComponents(Components);

	for ( int32 ComponentIndex = 0 ; ComponentIndex < Components.Num() ; ++ComponentIndex )
	{
		UActorComponent* ActorComponent = Components[ ComponentIndex ];
		if (ActorComponent->IsRegistered())
		{
			ActorComponent->CheckForErrors();
		}
	}
}
Exemplo n.º 8
0
void FLayers::RemoveViewFromActorViewVisibility( FLevelEditorViewportClient* ViewportClient )
{
	const int32 ViewIndex = ViewportClient->ViewIndex;

	// get the bit for the view index
	uint64 ViewBit = ((uint64)1 << ViewIndex);
	// get all bits under that that we want to keep
	uint64 KeepBits = ViewBit - 1;

	// Iterate over all actors, looking for actors in the specified layers.
	for( FActorIterator It(ViewportClient->GetWorld()) ; It ; ++It )
	{
		const TWeakObjectPtr< AActor > Actor = *It;

		if( !IsActorValidForLayer( Actor ) )
		{
			continue;
		}

		// remember original bits
		uint64 OriginalHiddenViews = Actor->HiddenEditorViews;

		uint64 Was = Actor->HiddenEditorViews;

		// slide all bits higher than ViewIndex down one since the view is being removed from Editor
		uint64 LowBits = Actor->HiddenEditorViews & KeepBits;

		// now slide the top bits down by ViewIndex + 1 (chopping off ViewBit)
		uint64 HighBits = Actor->HiddenEditorViews >> (ViewIndex + 1);
		// then slide back up by ViewIndex, which will now have erased ViewBit, as well as leaving 0 in the low bits
		HighBits = HighBits << ViewIndex;

		// put it all back together
		Actor->HiddenEditorViews = LowBits | HighBits;

		// reregister if we changed the visibility bits, as the rendering thread needs them
		if (OriginalHiddenViews == Actor->HiddenEditorViews)
		{
			continue;
		}

		// Find all registered primitive components and update the scene proxy with the actors updated visibility map
		TInlineComponentArray<UPrimitiveComponent*> Components;
		Actor->GetComponents(Components);

		for( int32 ComponentIdx = 0; ComponentIdx < Components.Num(); ++ComponentIdx )
		{
			UPrimitiveComponent* PrimitiveComponent = Components[ComponentIdx];
			if (PrimitiveComponent->IsRegistered())
			{
				// Push visibility to the render thread
				PrimitiveComponent->PushEditorVisibilityToProxy( Actor->HiddenEditorViews );
			}
		}
	}
}
Exemplo n.º 9
0
void FSCSEditorViewportClient::Tick(float DeltaSeconds)
{
	FEditorViewportClient::Tick(DeltaSeconds);

	// Register the selection override delegate for the preview actor's components
	TSharedPtr<SSCSEditor> SCSEditor = BlueprintEditorPtr.Pin()->GetSCSEditor();
	AActor* PreviewActor = GetPreviewActor();
	if (PreviewActor != nullptr)
	{
		TInlineComponentArray<UPrimitiveComponent*> PrimitiveComponents;
		PreviewActor->GetComponents(PrimitiveComponents);

		for (int32 CompIdx = 0; CompIdx < PrimitiveComponents.Num(); ++CompIdx)
		{
			UPrimitiveComponent* PrimComponent = PrimitiveComponents[CompIdx];
			if (!PrimComponent->SelectionOverrideDelegate.IsBound())
			{
				SCSEditor->SetSelectionOverride(PrimComponent);
			}
		}
	}
	else
	{
		InvalidatePreview(false);
	}

	if ( PreviewActor != LastPreviewActor.Get() || PreviewActor == nullptr || IsRealtime() )
	{
		LastPreviewActor = PreviewActor;

		Invalidate();
		RefreshPreviewBounds();
	}

	// Tick the preview scene world.
	if (!GIntraFrameDebuggingGameThread)
	{
		// Ensure that the preview actor instance is up-to-date for component editing (e.g. after compiling the Blueprint, the actor may be reinstanced outside of this class)
		if(PreviewActor != BlueprintEditorPtr.Pin()->GetBlueprintObj()->SimpleConstructionScript->GetComponentEditorActorInstance())
		{
			BlueprintEditorPtr.Pin()->GetBlueprintObj()->SimpleConstructionScript->SetComponentEditorActorInstance(PreviewActor);
		}

		// Allow full tick only if preview simulation is enabled and we're not currently in an active SIE or PIE session
		if(bIsSimulateEnabled && GEditor->PlayWorld == NULL && !GEditor->bIsSimulatingInEditor)
		{
			PreviewScene->GetWorld()->Tick(IsRealtime() ? LEVELTICK_All : LEVELTICK_TimeOnly, DeltaSeconds);
		}
		else
		{
			PreviewScene->GetWorld()->Tick(IsRealtime() ? LEVELTICK_ViewportsOnly : LEVELTICK_TimeOnly, DeltaSeconds);
		}
	}
}
void USceneCaptureComponent::HideActorComponents(AActor* InActor)
{
	if (InActor)
	{
		TInlineComponentArray<UPrimitiveComponent*> PrimitiveComponents;
		InActor->GetComponents(PrimitiveComponents);
		for (int32 ComponentIndex = 0, NumComponents = PrimitiveComponents.Num(); ComponentIndex < NumComponents; ++ComponentIndex)
		{
			HiddenComponents.AddUnique(PrimitiveComponents[ComponentIndex]);
		}
	}
}
Exemplo n.º 11
0
void FSCSEditorViewportClient::ProcessClick(class FSceneView& View, class HHitProxy* HitProxy, FKey Key, EInputEvent Event, uint32 HitX, uint32 HitY)
{
	if(HitProxy)
	{
		if(HitProxy->IsA(HInstancedStaticMeshInstance::StaticGetType()))
		{
			HInstancedStaticMeshInstance* InstancedStaticMeshInstanceProxy = ( ( HInstancedStaticMeshInstance* )HitProxy );

			TSharedPtr<ISCSEditorCustomization> Customization = BlueprintEditorPtr.Pin()->CustomizeSCSEditor(InstancedStaticMeshInstanceProxy->Component);
			if(Customization.IsValid() && Customization->HandleViewportClick(AsShared(), View, HitProxy, Key, Event, HitX, HitY))
			{
				Invalidate();
			}
		}
		else if(HitProxy->IsA(HActor::StaticGetType()))
		{
			HActor* ActorProxy = (HActor*)HitProxy;
			AActor* PreviewActor = GetPreviewActor();
			if(ActorProxy && ActorProxy->Actor && ActorProxy->Actor == PreviewActor && ActorProxy->PrimComponent != NULL)
			{
				TInlineComponentArray<USceneComponent*> SceneComponents;
				ActorProxy->Actor->GetComponents(SceneComponents);
	
				for(auto CompIt = SceneComponents.CreateConstIterator(); CompIt; ++CompIt)
				{
					USceneComponent* CompInstance = *CompIt;
					TSharedPtr<ISCSEditorCustomization> Customization = BlueprintEditorPtr.Pin()->CustomizeSCSEditor(CompInstance);
					if (Customization.IsValid() && Customization->HandleViewportClick(AsShared(), View, HitProxy, Key, Event, HitX, HitY))
					{
						break;
					}

					if (CompInstance == ActorProxy->PrimComponent)
					{
						const bool bIsCtrlKeyDown = Viewport->KeyState(EKeys::LeftControl) || Viewport->KeyState(EKeys::RightControl);
						if (BlueprintEditorPtr.IsValid())
						{
							// Note: This will find and select any node associated with the component instance that's attached to the proxy (including visualizers)
							BlueprintEditorPtr.Pin()->FindAndSelectSCSEditorTreeNode(CompInstance, bIsCtrlKeyDown);
						}
						break;
					}
				}
			}

			Invalidate();
		}

		// Pass to component vis manager
		//GUnrealEd->ComponentVisManager.HandleProxyForComponentVis(HitProxy);
	}
}
Exemplo n.º 12
0
	static UProperty *GetPropertyByName( UClass *InClass, const FName &Name )
	{
		if ( InClass == NULL )
			return NULL;

		UProperty *Property = GetPropertyByNameRecurse( InClass, Name.ToString() );
		if ( Property != NULL )
		{
			return Property;
		}

		AActor *AsActor = Cast<AActor>(InClass->ClassDefaultObject);
		if ( AsActor != NULL )
		{
			FString ComponentPropertyName = Name.ToString();
			int32 SplitIndex = 0;
			if ( ComponentPropertyName.FindChar( '.', SplitIndex ) )
			{
				//FString ComponentName = ComponentPropertyName.LeftChop(SplitIndex);
				ComponentPropertyName = ComponentPropertyName.RightChop(SplitIndex+1);

				TInlineComponentArray<UActorComponent*> ActorComponents;
				AsActor->GetComponents(ActorComponents);
				for ( auto ComponentIt = ActorComponents.CreateIterator(); ComponentIt; ++ComponentIt )
				{
					UActorComponent *Component = *ComponentIt;
					check( Component != NULL );
					/*
					if ( Component->GetName() != ComponentName )
					{
						continue;
					}
					*/

					Property = GetPropertyByNameRecurse( Component->GetClass(), ComponentPropertyName );
					if ( Property != NULL )
					{
						return Property;
					}
				}
			}
		}

		return NULL;
	}
Exemplo n.º 13
0
/**
* Determines if the provided actor is capable of having a material applied to it.
*
* @param	TargetActor	Actor to check for the validity of material application
*
* @return	true if the actor is valid for material application; false otherwise
*/
bool FActorFactoryAssetProxy::IsActorValidForMaterialApplication( AActor* TargetActor )
{
	bool bIsValid = false;

	//@TODO: PAPER2D: Extend this to support non mesh components (or make sprites a mesh component)

	// Check if the actor has a mesh or fog volume density. If so, it can likely have
	// a material applied to it. Otherwise, it cannot.
	if ( TargetActor )
	{
		TInlineComponentArray<UMeshComponent*> MeshComponents;
		TargetActor->GetComponents(MeshComponents);

		bIsValid = (MeshComponents.Num() > 0);
	}

	return bIsValid;
}
Exemplo n.º 14
0
void UUnrealEdEngine::SelectComponent(UActorComponent* Component, bool bInSelected, bool bNotify, bool bSelectEvenIfHidden)
{
	// Don't do any work if the component's selection state matches the target selection state
	const bool bComponentSelected = GetSelectedComponents()->IsSelected(Component);
	if (( bComponentSelected && !bInSelected ) || ( !bComponentSelected && bInSelected ))
	{
		if (bInSelected)
		{
			UE_LOG(LogEditorSelectUtils, Verbose, TEXT("Selected Component: %s"), *Component->GetClass()->GetName());
		}
		else
		{
			UE_LOG(LogEditorSelectUtils, Verbose, TEXT("Deselected Component: %s"), *Component->GetClass()->GetName());
		}

		GetSelectedComponents()->Select(Component, bInSelected);

		// Make sure the override delegate is bound properly
		auto SceneComponent = Cast<USceneComponent>(Component);
		if (SceneComponent)
		{
			FComponentEditorUtils::BindComponentSelectionOverride(SceneComponent, true);
		}

		// Update the selection visualization
		AActor* ComponentOwner = Component->GetOwner();
		if (ComponentOwner != nullptr)
		{
			TInlineComponentArray<UPrimitiveComponent*> PrimitiveComponents;
			ComponentOwner->GetComponents(PrimitiveComponents);

			for (int32 Idx = 0; Idx < PrimitiveComponents.Num(); ++Idx)
			{
				PrimitiveComponents[Idx]->PushSelectionToProxy();
			}
		}

		if (bNotify)
		{
			NoteSelectionChange();
		}
	}
}
Exemplo n.º 15
0
void UActorRecording::ProcessNewComponentArray(TInlineComponentArray<USceneComponent*>& ProspectiveComponents) const
{
	// Only iterate as far as the current size of the array (it may grow inside the loop)
	int32 LastIndex = ProspectiveComponents.Num();
	for(int32 Index = 0; Index < LastIndex; ++Index)
	{
		USceneComponent* NewComponent = ProspectiveComponents[Index];

		USceneComponent* Parent = ProspectiveComponents[Index]->GetAttachParent();

		while (Parent)
		{
			TWeakObjectPtr<USceneComponent> WeakParent(Parent);
			if (TrackedComponents.Contains(WeakParent) || ProspectiveComponents.Contains(Parent) || Parent->GetOwner() != NewComponent->GetOwner())
			{
				break;
			}
			else
			{
				ProspectiveComponents.Add(Parent);
			}

			Parent = Parent->GetAttachParent();
		}
	}

	// Sort parent first, to ensure that attachments get added properly
	TMap<USceneComponent*, int32> AttachmentDepths;
	for (USceneComponent* Component : ProspectiveComponents)
	{
		AttachmentDepths.Add(Component, GetAttachmentDepth(Component));
	}

	ProspectiveComponents.Sort(
		[&](USceneComponent& A, USceneComponent& B)
		{
			return *AttachmentDepths.Find(&A) < *AttachmentDepths.Find(&B);
		}
	);
}
Exemplo n.º 16
0
void FSCSEditorViewportClient::RefreshPreviewBounds()
{
	AActor* PreviewActor = GetPreviewActor();

	if(PreviewActor)
	{
		// Compute actor bounds as the sum of its visible parts
		TInlineComponentArray<UPrimitiveComponent*> PrimitiveComponents;
		PreviewActor->GetComponents(PrimitiveComponents);

		PreviewActorBounds = FBoxSphereBounds(ForceInitToZero);
		for(auto CompIt = PrimitiveComponents.CreateConstIterator(); CompIt; ++CompIt)
		{
			// Aggregate primitive components that either have collision enabled or are otherwise visible components in-game
			UPrimitiveComponent* PrimComp = *CompIt;
			if(PrimComp->IsRegistered() && (!PrimComp->bHiddenInGame || PrimComp->IsCollisionEnabled()) && PrimComp->Bounds.SphereRadius < HALF_WORLD_MAX)
			{
				PreviewActorBounds = PreviewActorBounds + PrimComp->Bounds;
			}
		}
	}
}
Exemplo n.º 17
0
static void DrawSnapVertices( AActor* Actor, float PointSize, FPrimitiveDrawInterface* PDI )
{
	TInlineComponentArray<UActorComponent*> Components;
	Actor->GetComponents(Components);

	// Get the closest vertex on each component
	for( int32 ComponentIndex  = 0; ComponentIndex < Components.Num(); ++ComponentIndex )
	{
		TSharedPtr<FVertexIterator> VertexGetter = MakeVertexIterator( Cast<UPrimitiveComponent>( Components[ComponentIndex] ) );
		if( VertexGetter.IsValid() )
		{
			FVertexIterator& VertexGetterRef = *VertexGetter;
			for( ; VertexGetterRef; ++VertexGetterRef )
			{
				PDI->DrawPoint( VertexGetterRef.Position(), VertexSnappingConstants::VertexHelperColor, PointSize, SDPG_World );
			}
		}
		else
		{
			PDI->DrawPoint( Actor->GetActorLocation(), VertexSnappingConstants::VertexHelperColor, PointSize, SDPG_World );
		}
	}
}
	static UProperty *GetPropertyByName( UObject *Target, UStruct *InStruct, const FString &PropertyName, void ** hContainerPtr, int32 &OutArrayIndex )
	{
		UProperty *Prop = GetPropertyByNameRecurse( Target->GetClass(), PropertyName, hContainerPtr, OutArrayIndex );
		if ( Prop == NULL )
		{
			AActor *AsActor = Cast<AActor>(Target);
			if ( AsActor != NULL )
			{
				FString ComponentPropertyName = PropertyName;
				int32 SplitIndex = 0;
				if ( ComponentPropertyName.FindChar( '.', SplitIndex ) )
				{
					//FString ComponentName = ComponentPropertyName.LeftChop(SplitIndex);
					ComponentPropertyName = ComponentPropertyName.RightChop(SplitIndex+1);

					TInlineComponentArray<UActorComponent*> ActorComponents;
					AsActor->GetComponents(ActorComponents);
					for ( auto ComponentIt = ActorComponents.CreateIterator(); ComponentIt && !Prop; ++ComponentIt )
					{
						UActorComponent *Component = *ComponentIt;
						check( Component != NULL );
						/*
						if ( Component->GetName() != ComponentName )
						{
							continue;
						}
						*/

						*hContainerPtr = Component;
						Prop = GetPropertyByNameRecurse( Component->GetClass(), ComponentPropertyName, hContainerPtr, OutArrayIndex );
					}
				}
			}
		}

		return Prop;
	}
bool UMatineeTrackAnimControlHelper::PreCreateKeyframe( UInterpTrack *Track, float fTime ) const
{
	KeyframeAddAnimSequence = NULL;
	UInterpTrackAnimControl	*AnimTrack = CastChecked<UInterpTrackAnimControl>(Track);
	UInterpGroup* Group = CastChecked<UInterpGroup>(Track->GetOuter());

	AActor* Actor = GetGroupActor(Track);
	if (!Actor)
	{
		// error message
		UE_LOG(LogSlateMatinee, Warning, TEXT("No Actor is selected. Select actor first."));
		return false;
	}

	USkeletalMeshComponent * SkelMeshComp = NULL;

	TInlineComponentArray<USkeletalMeshComponent*> SkeletalMeshComponents;
	Actor->GetComponents(SkeletalMeshComponents);

	for (int32 I=0; I<SkeletalMeshComponents.Num(); ++I)
	{
		USkeletalMeshComponent * CurSkelMeshComp = SkeletalMeshComponents[I];
		// if qualified to play animation, break
		if (CurSkelMeshComp->SkeletalMesh && CurSkelMeshComp->SkeletalMesh->Skeleton)
		{
			SkelMeshComp = CurSkelMeshComp;
			break;
		}
	}

	if (!SkelMeshComp)
	{
		UE_LOG(LogSlateMatinee, Warning, TEXT("SkeletalMeshComponent isn't found in the selected actor or it does not have Mesh/Skeleton set up in order to play animation"));
		return false;
	}

	USkeleton* Skeleton = SkelMeshComp->SkeletalMesh->Skeleton;
	if ( Skeleton )
	{
		// Show the dialog.
		FEdModeInterpEdit* Mode = (FEdModeInterpEdit*)GLevelEditorModeTools().GetActiveMode( FBuiltinEditorModes::EM_InterpEdit );
		check(Mode != NULL);
		check(Mode->InterpEd != NULL);
		
		TSharedPtr< SWindow > Parent = FSlateApplication::Get().GetActiveTopLevelWindow();
		if ( Parent.IsValid() )
		{
			FAssetPickerConfig AssetPickerConfig;
			AssetPickerConfig.OnAssetSelected = FOnAssetSelected::CreateUObject( this, &UMatineeTrackAnimControlHelper::OnAddKeyTextEntry, Mode->InterpEd, Track );
			AssetPickerConfig.bAllowNullSelection = false;
			AssetPickerConfig.InitialAssetViewType = EAssetViewType::List;

			// Filter config
			AssetPickerConfig.Filter.ClassNames.Add(UAnimSequence::StaticClass()->GetFName());
			AssetPickerConfig.Filter.TagsAndValues.Add(TEXT("Skeleton"), FAssetData(Skeleton).GetExportTextName());

			FContentBrowserModule& ContentBrowserModule = FModuleManager::Get().LoadModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser"));

			FMenuBuilder MenuBuilder(true, NULL);
			MenuBuilder.BeginSection(NAME_None, LOCTEXT("MatineeAnimPicker", "Browse"));
			{
				TSharedPtr<SBox> MenuEntry = SNew(SBox)
				.WidthOverride(300.0f)
				.HeightOverride(300.f)
				[
					ContentBrowserModule.Get().CreateAssetPicker(AssetPickerConfig)
				];
				MenuBuilder.AddWidget(MenuEntry.ToSharedRef(), FText::GetEmpty(), true);
			}
			MenuBuilder.EndSection();

			EntryMenu = FSlateApplication::Get().PushMenu(
				Parent.ToSharedRef(),
				FWidgetPath(),
				MenuBuilder.MakeWidget(),
				FSlateApplication::Get().GetCursorPos(),
				FPopupTransitionEffect(FPopupTransitionEffect::TypeInPopup)
				);
		}
	}
	else
	{
		FMessageDialog::Open( EAppMsgType::Ok, NSLOCTEXT("UnrealEd", "NoAnimSeqsFound", "No AnimSequences Found. Make sure to load AnimSequences.") );
	}

	return false;
}
Exemplo n.º 20
0
void UUnrealEdEngine::UpdateVolumeActorVisibility( UClass* InVolumeActorClass, FLevelEditorViewportClient* InViewport )
{
	TSubclassOf<AActor> VolumeClassToCheck = InVolumeActorClass ? InVolumeActorClass : AVolume::StaticClass();
	
	// Build a list of actors that need to be updated.  Only take actors of the passed in volume class.  
	UWorld* World = InViewport ? InViewport->GetWorld() : GWorld;
	TArray< AActor *> ActorsToUpdate;
	for( TActorIterator<AActor> It( World, VolumeClassToCheck ); It; ++It)
	{
		ActorsToUpdate.Add(*It);
	}

	if( ActorsToUpdate.Num() > 0 )
	{
		TArray< AActor* > ActorsThatChanged;
		if( !InViewport )
		{
			// Update the visibility state of each actor for each viewport
			for( int32 ViewportIdx = 0; ViewportIdx < LevelViewportClients.Num(); ++ViewportIdx )
			{
				FLevelEditorViewportClient& ViewClient = *LevelViewportClients[ViewportIdx];
				{
					// Only update the editor frame clients as those are the only viewports right now that show volumes.
					InternalUpdateVolumeActorVisibility( ActorsToUpdate, ViewClient, ActorsThatChanged );
					if( ActorsThatChanged.Num() )
					{
						// If actor visibility changed in the viewport, it needs to be redrawn
						ViewClient.Invalidate();
					}
				}
			}
		}
		else
		{
			// Only update the editor frame clients as those are the only viewports right now that show volumes.
			InternalUpdateVolumeActorVisibility( ActorsToUpdate, *InViewport, ActorsThatChanged );
			if( ActorsThatChanged.Num() )
			{	
				// If actor visibility changed in the viewport, it needs to be redrawn
				InViewport->Invalidate();
			}
		}

		// Push all changes in the actors to the scene proxy so the render thread correctly updates visibility
		for( int32 ActorIdx = 0; ActorIdx < ActorsThatChanged.Num(); ++ActorIdx )
		{
			AActor* ActorToUpdate = ActorsThatChanged[ ActorIdx ];

			// Find all registered primitive components and update the scene proxy with the actors updated visibility map
			TInlineComponentArray<UPrimitiveComponent*> PrimitiveComponents;
			ActorToUpdate->GetComponents(PrimitiveComponents);

			for( int32 ComponentIdx = 0; ComponentIdx < PrimitiveComponents.Num(); ++ComponentIdx )
			{
				UPrimitiveComponent* PrimitiveComponent = PrimitiveComponents[ComponentIdx];
				if (PrimitiveComponent->IsRegistered())
				{
					// Push visibility to the render thread
					PrimitiveComponent->PushEditorVisibilityToProxy( ActorToUpdate->HiddenEditorViews );
				}
			}
		}
	}
}
Exemplo n.º 21
0
FSnappingVertex FVertexSnappingImpl::GetClosestVertex( const TArray<FSnapActor>& Actors, const FVertexSnappingArgs& InArgs )
{
	// The current closest distance
	float ClosestDistance = FLT_MAX;

	const FPlane& ActorPlane = InArgs.ActorPlane;
	EAxisList::Type CurrentAxis = InArgs.CurrentAxis;
	const FSceneView* View = InArgs.SceneView;
	const FVector& CurrentLocation = InArgs.CurrentLocation;
	const FVector2D& MousePosition = InArgs.MousePosition;

	FSnappingVertex ClosestLocation( CurrentLocation );

	AActor* ClosestActor = NULL;
	// Find the closest vertex on each actor and then from that list find the closest vertex
	for( int32 ActorIndex = 0; ActorIndex < Actors.Num(); ++ActorIndex )
	{
		const FSnapActor& SnapActor = Actors[ActorIndex];
		AActor* Actor = SnapActor.Actor;

		// Get the closest vertex on each component
		TInlineComponentArray<UPrimitiveComponent*> PrimitiveComponents;
		Actor->GetComponents(PrimitiveComponents);

		for( int32 ComponentIndex  = 0; ComponentIndex < PrimitiveComponents.Num(); ++ComponentIndex )
		{
			FSnappingVertex ClosestLocationOnComponent( CurrentLocation );
			if( !GetClosestVertexOnComponent( SnapActor, PrimitiveComponents[ComponentIndex], InArgs, ClosestLocationOnComponent ) )
			{
				ClosestLocationOnComponent.Position = Actor->GetActorLocation();
				ClosestLocationOnComponent.Normal = FVector::ZeroVector;
			}

			float Distance = 0;
			if( CurrentAxis != EAxisList::Screen )
			{
				// Compute the distance from the point being snapped.  When not in screen space we snap to the plane created by the current closest vertex
				Distance = ActorPlane.PlaneDot( ClosestLocationOnComponent.Position );
			}
			else
			{
				// Favor the vertex closest to the mouse in screen space
				FVector2D ComponentLocPixel;
				if( View->WorldToPixel( ClosestLocationOnComponent.Position, ComponentLocPixel ) )
				{
					Distance = FVector::DistSquared( FVector( MousePosition, 0 ), FVector( ComponentLocPixel, 0 ) );
				}
			}

			if( 
				// A close vertex must have been found
				ClosestLocationOnComponent.Position != CurrentLocation 
				// we must have made some movement
				&& !FMath::IsNearlyZero(Distance) 
				// If not in screen space the vertex cannot be behind the point being snapped
				&& ( CurrentAxis == EAxisList::Screen || !FMath::IsNegativeFloat( Distance ) )
				// The vertex must be closer than the current closest vertex
				&& Distance < ClosestDistance )
			{
				ClosestActor = Actor;
				ClosestDistance = Distance;
				ClosestLocation = ClosestLocationOnComponent;
			}
		}
	}

	if( InArgs.bDrawVertexHelpers )
	{
		if(ActorVertsToDraw.IsValid())
		{
			ActorVertsToFade.Add(ActorVertsToDraw, FApp::GetCurrentTime());
		}

		ActorVertsToFade.Remove(ClosestActor);
		ActorVertsToDraw = ClosestActor;
	}
	else
	{
		ActorVertsToDraw = nullptr;
		ActorVertsToFade.Empty();
	}


	return ClosestLocation;
}
USceneComponent* USimpleConstructionScript::GetSceneRootComponentTemplate(USCS_Node** OutSCSNode) const
{
	UBlueprint* Blueprint = GetBlueprint();

	UClass* GeneratedClass = GetOwnerClass();

	if(OutSCSNode)
	{
		*OutSCSNode = nullptr;
	}

	// Get the Blueprint class default object
	AActor* CDO = nullptr;
	if(GeneratedClass != nullptr)
	{
		CDO = Cast<AActor>(GeneratedClass->GetDefaultObject(false));
	}

	// If the generated class does not yet have a CDO, defer to the parent class
	if(CDO == nullptr && Blueprint->ParentClass != nullptr)
	{
		CDO = Cast<AActor>(Blueprint->ParentClass->GetDefaultObject(false));
	}

	// Check to see if we already have a native root component template
	USceneComponent* RootComponentTemplate = nullptr;
	if(CDO != nullptr)
	{
		// If the root component property is not set, the first available scene component will be used as the root. This matches what's done in the SCS editor.
		RootComponentTemplate = CDO->GetRootComponent();
		if(!RootComponentTemplate)
		{
			TInlineComponentArray<USceneComponent*> SceneComponents;
			CDO->GetComponents(SceneComponents);
			if(SceneComponents.Num() > 0)
			{
				RootComponentTemplate = SceneComponents[0];
			}
		}
	}

	// Don't add the default scene root if we already have a native scene root component
	if(!RootComponentTemplate)
	{
		// Get the Blueprint hierarchy
		TArray<UBlueprint*> BPStack;
		if(Blueprint->GeneratedClass != nullptr)
		{
			UBlueprint::GetBlueprintHierarchyFromClass(Blueprint->GeneratedClass, BPStack);
		}
		else if(Blueprint->ParentClass != nullptr)
		{
			UBlueprint::GetBlueprintHierarchyFromClass(Blueprint->ParentClass, BPStack);
		}

		// Note: Normally if the Blueprint has a parent, we can assume that the parent already has a scene root component set,
		// ...but we'll run through the hierarchy just in case there are legacy BPs out there that might not adhere to this assumption.
		TArray<const USimpleConstructionScript*> SCSStack;
		SCSStack.Add(this);

		for(int32 StackIndex = 0; StackIndex < BPStack.Num(); ++StackIndex)
		{
			if(BPStack[StackIndex] && BPStack[StackIndex]->SimpleConstructionScript && !SCSStack.Contains(BPStack[StackIndex]->SimpleConstructionScript))
			{
				// UBlueprint::GetBlueprintHierarchyFromClass returns first children then parents. So we need to revert the order.
				SCSStack.Insert(BPStack[StackIndex]->SimpleConstructionScript, 0);
			}
		}

		for(int32 StackIndex = 0; StackIndex < SCSStack.Num() && !RootComponentTemplate; ++StackIndex)
		{
			// Check for any scene component nodes in the root set that are not the default scene root
			const TArray<USCS_Node*>& SCSRootNodes = SCSStack[StackIndex]->GetRootNodes();
			for(int32 RootNodeIndex = 0; RootNodeIndex < SCSRootNodes.Num() && RootComponentTemplate == nullptr; ++RootNodeIndex)
			{
				USCS_Node* RootNode = SCSRootNodes[RootNodeIndex];
				if(RootNode != nullptr
					&& RootNode != DefaultSceneRootNode
					&& RootNode->ComponentTemplate != nullptr
					&& RootNode->ComponentTemplate->IsA<USceneComponent>())
				{
					if(OutSCSNode)
					{
						*OutSCSNode = RootNode;
					}
					
					RootComponentTemplate = Cast<USceneComponent>(RootNode->ComponentTemplate);
				}
			}
		}
	}

	return RootComponentTemplate;
}
void ADebugCameraHUD::PostRender()
{
	Super::PostRender();

	if (bShowHUD)
	{
		ADebugCameraController* DCC = Cast<ADebugCameraController>( PlayerOwner );
		UFont* RenderFont = GEngine->GetSmallFont();
		if( DCC != NULL )
		{
			FFontRenderInfo FontRenderInfo = Canvas->CreateFontRenderInfo(false, true);

			Canvas->SetDrawColor(64, 64, 255, 255);
			FString MyText = TEXT("Debug Camera");
			float xl, yl;
			Canvas->StrLen(RenderFont, MyText, xl, yl);
			float X = Canvas->SizeX * 0.05f;
			float Y = yl;//*1.67;
			yl += 2*Y;
			Canvas->DrawText(RenderFont, MyText, X, yl, 1.f, 1.f, FontRenderInfo);

			Canvas->SetDrawColor(200, 200, 128, 255);

			FVector const CamLoc = DCC->PlayerCameraManager->GetCameraLocation();
			FRotator const CamRot = DCC->PlayerCameraManager->GetCameraRotation();
			float const CamFOV = DCC->PlayerCameraManager->GetFOVAngle();

			yl += Y;
			
			FString const LocRotString = FString::Printf(TEXT("Loc=(%.1f, %.1f, %.1f) Rot=(%.1f, %.1f, %.1f)"), CamLoc.X, CamLoc.Y, CamLoc.Z, CamRot.Pitch, CamRot.Yaw, CamRot.Roll);
			Canvas->DrawText(RenderFont, LocRotString, X, yl, 1.f, 1.f, FontRenderInfo);
			yl += Y;
			
			FString const FOVString = FString::Printf(TEXT("HFOV=%.1f"), CamFOV);
			Canvas->DrawText(RenderFont, FOVString, X, yl, 1.f, 1.f, FontRenderInfo);
			yl += Y;
			
			FString const SpeedScaleString = FString::Printf(TEXT("SpeedScale=%.2fx"), DCC->SpeedScale);
			Canvas->DrawText(RenderFont, SpeedScaleString, X, yl, 1.f, 1.f, FontRenderInfo);
			yl += Y;
			
			FString const SpeedString = FString::Printf(TEXT("MaxSpeed=%.1f"), DCC->GetSpectatorPawn() && DCC->GetSpectatorPawn()->GetMovementComponent() ? DCC->GetSpectatorPawn()->GetMovementComponent()->GetMaxSpeed() : 0.f);
			Canvas->DrawText(RenderFont, SpeedString, X, yl, 1.f, 1.f, FontRenderInfo);
			yl += Y;

			//Canvas->DrawText(FString::Printf(TEXT("CamLoc:%s CamRot:%s"), *CamLoc.ToString(), *CamRot.ToString() ));

			const TCHAR* CVarComplexName = TEXT("g.DebugCameraTraceComplex");
			bool bTraceComplex = true;

#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
			bTraceComplex = CVarDebugCameraTraceComplex.GetValueOnGameThread() != 0;
#endif

			FCollisionQueryParams TraceParams(NAME_None, bTraceComplex, this);
			FHitResult Hit;
			bool bHit = GetWorld()->LineTraceSingleByChannel(Hit, CamLoc, CamRot.Vector() * 100000.f + CamLoc, ECC_Pawn, TraceParams);

			yl += Y;
			Canvas->DrawText(RenderFont, FString::Printf(TEXT("Trace info (%s = %d):"), CVarComplexName, bTraceComplex ? 1 : 0), X, yl, 1.f, 1.f, FontRenderInfo);

			if( bHit )
			{
				AActor* HitActor = Hit.GetActor();
				yl += Y;
				Canvas->DrawText(RenderFont, FString::Printf(TEXT("HitLoc:%s HitNorm:%s"), *Hit.Location.ToString(), *Hit.Normal.ToString() ), X, yl, 1.f, 1.f, FontRenderInfo);
				yl += Y;
				Canvas->DrawText(RenderFont, FString::Printf(TEXT("HitDist: %f"), Hit.Distance), X, yl, 1.f, 1.f, FontRenderInfo);
				yl += Y;
				Canvas->DrawText(RenderFont, FString::Printf(TEXT("HitActor: '%s'"), HitActor ? *HitActor->GetFName().ToString() : TEXT("<NULL>")), X, yl, 1.f, 1.f, FontRenderInfo);
				yl += Y;
				Canvas->DrawText(RenderFont, FString::Printf(TEXT("HitComponent: '%s'"), Hit.Component.Get() ? *Hit.Component.Get()->GetFName().ToString() : TEXT("<NULL>")), X, yl, 1.f, 1.f, FontRenderInfo);
				yl += Y;
				Canvas->DrawText(RenderFont, FString::Printf(TEXT("HitActor Class: '%s'"), HitActor && HitActor->GetClass() ? *HitActor->GetClass()->GetName() : TEXT("<Not Found>") ), X, yl, 1.f, 1.f, FontRenderInfo);
				yl += Y;
				Canvas->DrawText(RenderFont, FString::Printf(TEXT("HitActorPath: '%s'"), HitActor ? *HitActor->GetPathName() : TEXT("<Not Found>")), X, yl, 1.f, 1.f, FontRenderInfo);
				yl += Y;

				bool bFoundMaterial = false;
				if ( Hit.Component != NULL )
				{
					bFoundMaterial = DisplayMaterials( X, yl, Y, Cast<UMeshComponent>(Hit.Component.Get()) );
				}
				else
				{
					TInlineComponentArray<UMeshComponent*> Components;
					GetComponents(Components);

					for ( int32 i=0; i<Components.Num(); i++ )
					{
						UMeshComponent* MeshComp = Components[i];
						if ( MeshComp->IsRegistered() )
						{
							bFoundMaterial = bFoundMaterial || DisplayMaterials( X, yl, Y, MeshComp );	
						}
					}
				}
				if ( bFoundMaterial == false )
				{
					yl += Y;
					Canvas->DrawText(RenderFont, "Material: NULL", X + Y, yl, 1.f, 1.f, FontRenderInfo );
				}
				DrawDebugLine( GetWorld(), Hit.Location, Hit.Location+Hit.Normal*30.f, FColor::White );
			}
			else
			{
				yl += Y;
				Canvas->DrawText( RenderFont, TEXT("No trace Hit"), X, yl, 1.f, 1.f, FontRenderInfo);
			}

			if ( DCC->bShowSelectedInfo && DCC->SelectedActor != NULL )
			{
				yl += Y;
				Canvas->DrawText(RenderFont,  FString::Printf(TEXT("Selected actor: '%s'"), *DCC->SelectedActor->GetFName().ToString()), X, yl, 1.f, 1.f, FontRenderInfo);
				DisplayMaterials( X, yl, Y, Cast<UMeshComponent>(DCC->SelectedComponent) );
			}


			// controls display
			yl += Y*15;
			
			Canvas->SetDrawColor(64, 64, 255, 255);
			Canvas->DrawText(RenderFont, TEXT("Controls"), X, yl, 1.f, 1.f, FontRenderInfo);
			yl += Y;
			
			Canvas->SetDrawColor(200, 200, 128, 255);
			Canvas->DrawText(RenderFont, TEXT("FOV +/-: ,/. or DPad Up/Down"), X, yl, 1.f, 1.f, FontRenderInfo);
			yl += Y;
			
			Canvas->DrawText(RenderFont, TEXT("Speed +/-: MouseWheel or +/- or LB/RB"), X, yl, 1.f, 1.f, FontRenderInfo);
			yl += Y;
			
			Canvas->DrawText(RenderFont, TEXT("Freeze Rendering: F or YButton"), X, yl, 1.f, 1.f, FontRenderInfo);
			yl += Y;			
			
			Canvas->DrawText(RenderFont, TEXT("Toggle Display: BackSpace or XButton"), X, yl, 1.f, 1.f, FontRenderInfo);
			yl += Y;
		}
	}
}
Exemplo n.º 24
0
USceneComponent* USCS_Node::GetParentComponentTemplate(UBlueprint* InBlueprint) const
{
	USceneComponent* ParentComponentTemplate = NULL;
	if(ParentComponentOrVariableName != NAME_None)
	{
		check(InBlueprint != NULL && InBlueprint->GeneratedClass != NULL);

		// If the parent component template is found in the 'Components' array of the CDO (i.e. native)
		if(bIsParentComponentNative)
		{
			// Access the Blueprint CDO
			AActor* CDO = InBlueprint->GeneratedClass->GetDefaultObject<AActor>();
			if(CDO != NULL)
			{
				// Find the component template in the CDO that matches the specified name
				TInlineComponentArray<USceneComponent*> Components;
				CDO->GetComponents(Components);

				for(auto CompIt = Components.CreateIterator(); CompIt; ++CompIt)
				{
					USceneComponent* CompTemplate = *CompIt;
					if(CompTemplate->GetFName() == ParentComponentOrVariableName)
					{
						// Found a match; this is our parent, we're done
						ParentComponentTemplate = CompTemplate;
						break;
					}
				}
			}
		}
		// Otherwise the parent component template is found in a parent Blueprint's SCS tree (i.e. non-native)
		else
		{
			// Get the Blueprint hierarchy
			TArray<UBlueprint*> ParentBPStack;
			UBlueprint::GetBlueprintHierarchyFromClass(InBlueprint->GeneratedClass, ParentBPStack);

			// Find the parent Blueprint in the hierarchy
			for(int32 StackIndex = ParentBPStack.Num() - 1; StackIndex > 0; --StackIndex)
			{
				UBlueprint* ParentBlueprint = ParentBPStack[StackIndex];
				if(ParentBlueprint != NULL
					&& ParentBlueprint->SimpleConstructionScript != NULL
					&& ParentBlueprint->GeneratedClass->GetFName() == ParentComponentOwnerClassName)
				{
					// Find the SCS node with a variable name that matches the specified name
					TArray<USCS_Node*> ParentSCSNodes = ParentBlueprint->SimpleConstructionScript->GetAllNodes();
					for(int32 ParentNodeIndex = 0; ParentNodeIndex < ParentSCSNodes.Num(); ++ParentNodeIndex)
					{
						USceneComponent* CompTemplate = Cast<USceneComponent>(ParentSCSNodes[ParentNodeIndex]->ComponentTemplate);
						if(CompTemplate != NULL && ParentSCSNodes[ParentNodeIndex]->VariableName == ParentComponentOrVariableName)
						{
							// Found a match; this is our parent, we're done
							ParentComponentTemplate = CompTemplate;
							break;
						}
					}
				}
			}
		}
	}

	return ParentComponentTemplate;
}
Exemplo n.º 25
0
void AActor::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
	UProperty* PropertyThatChanged = PropertyChangedEvent.Property;
	FName PropertyName = PropertyThatChanged != NULL ? PropertyThatChanged->GetFName() : NAME_None;
	
	const bool bTransformationChanged = (PropertyName == Name_RelativeLocation || PropertyName == Name_RelativeRotation || PropertyName == Name_RelativeScale3D);

	// During SIE, allow components to reregistered and reconstructed in PostEditChangeProperty.
	// This is essential as construction is deferred during spawning / duplication when in SIE.
	if ((GEditor && GEditor->bIsSimulatingInEditor) || ReregisterComponentsWhenModified())
	{
		// In the Undo case we have an annotation storing information about constructed components and we do not want
		// to improperly apply out of date changes so we need to skip registration of all blueprint created components
		// and defer instance components attached to them until after rerun
		if (CurrentTransactionAnnotation.IsValid())
		{
			UnregisterAllComponents();

			TInlineComponentArray<UActorComponent*> Components;
			GetComponents(Components);

			Components.Sort([](UActorComponent& A, UActorComponent& B)
			{
				if (&B == B.GetOwner()->GetRootComponent())
				{
					return false;
				}
				if (USceneComponent* ASC = Cast<USceneComponent>(&A))
				{
					if (ASC->GetAttachParent() == &B)
					{
						return false;
					}
				}
				return true;
			});

			bool bRequiresReregister = false;
			for (UActorComponent* Component : Components)
			{
				if (Component->CreationMethod == EComponentCreationMethod::Native)
				{
					Component->RegisterComponent();
				}
				else if (Component->CreationMethod == EComponentCreationMethod::Instance)
				{
					USceneComponent* SC = Cast<USceneComponent>(Component);
					if (SC == nullptr || SC == RootComponent || (SC->GetAttachParent() && SC->GetAttachParent()->IsRegistered()))
					{
						Component->RegisterComponent();
					}
					else
					{
						bRequiresReregister = true;
					}
				}
				else
				{
					bRequiresReregister = true;
				}
			}

			RerunConstructionScripts();

			if (bRequiresReregister)
			{
				ReregisterAllComponents();
			}
		}
		else
		{
			UnregisterAllComponents();
			RerunConstructionScripts();
			ReregisterAllComponents();
		}
	}

	// Let other systems know that an actor was moved
	if (bTransformationChanged)
	{
		GEngine->BroadcastOnActorMoved( this );
	}

	if (GetWorld())
	{
		GetWorld()->bDoDelayedUpdateCullDistanceVolumes = true;
	}

	FEditorSupportDelegates::UpdateUI.Broadcast();
	Super::PostEditChangeProperty(PropertyChangedEvent);
}
int32 FComponentEditorUtils::DeleteComponents(const TArray<UActorComponent*>& ComponentsToDelete, UActorComponent*& OutComponentToSelect)
{
	int32 NumDeletedComponents = 0;

	TArray<AActor*> ActorsToReconstruct;

	for (auto ComponentToDelete : ComponentsToDelete)
	{
		if (ComponentToDelete->CreationMethod != EComponentCreationMethod::Instance)
		{
			// We can only delete instance components, so retain selection on the un-deletable component
			OutComponentToSelect = ComponentToDelete;
			continue;
		}

		AActor* Owner = ComponentToDelete->GetOwner();
		check(Owner != nullptr);

		// If necessary, determine the component that should be selected following the deletion of the indicated component
		if (!OutComponentToSelect || ComponentToDelete == OutComponentToSelect)
		{
			USceneComponent* RootComponent = Owner->GetRootComponent();
			if (RootComponent != ComponentToDelete)
			{
				// Worst-case, the root can be selected
				OutComponentToSelect = RootComponent;

				if (auto ComponentToDeleteAsSceneComp = Cast<USceneComponent>(ComponentToDelete))
				{
					if (USceneComponent* ParentComponent = ComponentToDeleteAsSceneComp->GetAttachParent())
					{
						// The component to delete has a parent, so we select that in the absence of an appropriate sibling
						OutComponentToSelect = ParentComponent;

						// Try to select the sibling that immediately precedes the component to delete
						TArray<USceneComponent*> Siblings;
						ParentComponent->GetChildrenComponents(false, Siblings);
						for (int32 i = 0; i < Siblings.Num() && ComponentToDelete != Siblings[i]; ++i)
						{
							if (!Siblings[i]->IsPendingKill())
							{
								OutComponentToSelect = Siblings[i];
							}
						}
					}
				}
				else
				{
					// For a non-scene component, try to select the preceding non-scene component
					TInlineComponentArray<UActorComponent*> ActorComponents;
					Owner->GetComponents(ActorComponents);
					for (int32 i = 0; i < ActorComponents.Num() && ComponentToDelete != ActorComponents[i]; ++i)
					{
						if (!ActorComponents[i]->IsA(USceneComponent::StaticClass()))
						{
							OutComponentToSelect = ActorComponents[i];
						}
					}
				}
			}
			else
			{
				OutComponentToSelect = nullptr;
			}
		}

		// Defer reconstruction
		ActorsToReconstruct.AddUnique(Owner);

		// Actually delete the component
		ComponentToDelete->Modify();
		ComponentToDelete->DestroyComponent(true);
		NumDeletedComponents++;
	}

	// Reconstruct owner instance(s) after deletion
	for(auto ActorToReconstruct : ActorsToReconstruct)
	{
		ActorToReconstruct->RerunConstructionScripts();
	}

	return NumDeletedComponents;
}
Exemplo n.º 27
0
/**
* Attempts to apply the material to the specified actor.
*
* @param	TargetActor		the actor to apply the material to
* @param	MaterialToApply	the material to apply to the actor
* @param    OptionalMaterialSlot the material slot to apply to.
*
* @return	true if the material was successfully applied to the actor
*/
bool FActorFactoryAssetProxy::ApplyMaterialToActor( AActor* TargetActor, UMaterialInterface* MaterialToApply, int32 OptionalMaterialSlot )
{
	bool bResult = false;

	if ( TargetActor != NULL && MaterialToApply != NULL )
	{
		ALandscapeProxy* Landscape = Cast<ALandscapeProxy>(TargetActor);
		if (Landscape != NULL)
		{
			UProperty* MaterialProperty = FindField<UProperty>(ALandscapeProxy::StaticClass(), "LandscapeMaterial");
			Landscape->PreEditChange(MaterialProperty);
			Landscape->LandscapeMaterial = MaterialToApply;
			FPropertyChangedEvent PropertyChangedEvent(MaterialProperty);
			Landscape->PostEditChangeProperty(PropertyChangedEvent);
			bResult = true;
		}
		else
		{
			TArray<UActorComponent*> EditableComponents;
			FActorEditorUtils::GetEditableComponents( TargetActor, EditableComponents );

			// Some actors could potentially have multiple mesh components, so we need to store all of the potentially valid ones
			// (or else perform special cases with IsA checks on the target actor)
			TArray<USceneComponent*> FoundMeshComponents;

			// Find which mesh the user clicked on first.
			TInlineComponentArray<USceneComponent*> SceneComponents;
			TargetActor->GetComponents(SceneComponents);

			for ( int32 ComponentIdx=0; ComponentIdx < SceneComponents.Num(); ComponentIdx++ )
			{
				USceneComponent* SceneComp = SceneComponents[ComponentIdx];
				
				// Only apply the material to editable components.  Components which are not exposed are not intended to be changed.
				if( EditableComponents.Contains( SceneComp ) )
				{
					UMeshComponent* MeshComponent = Cast<UMeshComponent>(SceneComp);

					if((MeshComponent && MeshComponent->IsRegistered()) ||
						SceneComp->IsA<UDecalComponent>())
					{
						// Intentionally do not break the loop here, as there could be potentially multiple mesh components
						FoundMeshComponents.AddUnique( SceneComp );
					}
				}
			}

			if ( FoundMeshComponents.Num() > 0 )
			{
				// Check each component that was found
				for ( TArray<USceneComponent*>::TConstIterator MeshCompIter( FoundMeshComponents ); MeshCompIter; ++MeshCompIter )
				{
					USceneComponent* SceneComp = *MeshCompIter;
					bResult = FComponentEditorUtils::AttemptApplyMaterialToComponent(SceneComp, MaterialToApply, OptionalMaterialSlot);
				}
			}
		}
	}


	return bResult;
}
Exemplo n.º 28
0
/**
 * Removes the actor from its level's actor list and generally cleans up the engine's internal state.
 * What this function does not do, but is handled via garbage collection instead, is remove references
 * to this actor from all other actors, and kill the actor's resources.  This function is set up so that
 * no problems occur even if the actor is being destroyed inside its recursion stack.
 *
 * @param	ThisActor				Actor to remove.
 * @param	bNetForce				[opt] Ignored unless called during play.  Default is false.
 * @param	bShouldModifyLevel		[opt] If true, Modify() the level before removing the actor.  Default is true.
 * @return							true if destroy, false if actor couldn't be destroyed.
 */
bool UWorld::DestroyActor( AActor* ThisActor, bool bNetForce, bool bShouldModifyLevel )
{
	check(ThisActor);
	check(ThisActor->IsValidLowLevel());
	//UE_LOG(LogSpawn, Log,  "Destroy %s", *ThisActor->GetClass()->GetName() );

	if (ThisActor->GetWorld() == NULL)
	{
		UE_LOG(LogSpawn, Warning, TEXT("Destroying %s, which doesn't have a valid world pointer"), *ThisActor->GetPathName());
	}

	// If already on list to be deleted, pretend the call was successful.
	// We don't want recursive calls to trigger destruction notifications multiple times.
	if (ThisActor->IsPendingKillPending())
	{
		return true;
	}

	// In-game deletion rules.
	if( IsGameWorld() )
	{
		// Never destroy the world settings actor. This used to be enforced by bNoDelete and is actually needed for 
		// seamless travel and network games.
		if (GetWorldSettings() == ThisActor)
		{
			return false;
		}

		// Can't kill if wrong role.
		if( ThisActor->Role!=ROLE_Authority && !bNetForce && !ThisActor->bNetTemporary )
		{
			return false;
		}

		// Don't destroy player actors.
		APlayerController* PC = Cast<APlayerController>(ThisActor);
		if ( PC )
		{
			UNetConnection* C = Cast<UNetConnection>(PC->Player);
			if( C )
			{	
				if( C->Channels[0] && C->State!=USOCK_Closed )
				{
					C->bPendingDestroy = true;
					C->Channels[0]->Close();
				}
				return false;
			}
		}
	}
	else
	{
		ThisActor->Modify();
	}

	// Prevent recursion
	//FMarkActorIsBeingDestroyed MarkActorIsBeingDestroyed(ThisActor);

	// Notify the texture streaming manager about the destruction of this actor.
	IStreamingManager::Get().NotifyActorDestroyed( ThisActor );

	// Tell this actor it's about to be destroyed.
	ThisActor->Destroyed();

	// Detach this actor's children
	TArray<AActor*> AttachedActors;
	ThisActor->GetAttachedActors(AttachedActors);

	if (AttachedActors.Num() > 0)
	{
		TInlineComponentArray<USceneComponent*> SceneComponents;
		ThisActor->GetComponents(SceneComponents);

		for (TArray< AActor* >::TConstIterator AttachedActorIt(AttachedActors); AttachedActorIt; ++AttachedActorIt)
		{
			AActor* ChildActor = *AttachedActorIt;
			if (ChildActor != NULL)
			{
				for (auto SceneCompIter = SceneComponents.CreateIterator(); SceneCompIter; ++SceneCompIter)
				{
					ChildActor->DetachSceneComponentsFromParent(*SceneCompIter, true);
				}
#if WITH_EDITOR
				if( GIsEditor )
				{
					GEngine->BroadcastLevelActorDetached(ChildActor, ThisActor);
				}
#endif
			}
		}
	}

	// Detach from anything we were attached to
	USceneComponent* RootComp = ThisActor->GetRootComponent();
	if( RootComp != NULL && RootComp->AttachParent != NULL)
	{
		AActor* OldParentActor = RootComp->AttachParent->GetOwner();
		if (OldParentActor)
		{
			OldParentActor->Modify();
		}

		ThisActor->DetachRootComponentFromParent();

#if WITH_EDITOR
		if( GIsEditor )
		{
			GEngine->BroadcastLevelActorDetached(ThisActor, OldParentActor);
		}
#endif
	}

	ThisActor->ClearComponentOverlaps();

	// If this actor has an owner, notify it that it has lost a child.
	if( ThisActor->GetOwner() )
	{
		ThisActor->SetOwner(NULL);
	}
	// Notify net players that this guy has been destroyed.
	UNetDriver* ActorNetDriver = GEngine->FindNamedNetDriver(this, ThisActor->NetDriverName);
	if (ActorNetDriver)
	{
		ActorNetDriver->NotifyActorDestroyed(ThisActor);
	}

	if ( DemoNetDriver )
	{
		DemoNetDriver->NotifyActorDestroyed( ThisActor );
	}

	// Remove the actor from the actor list.
	RemoveActor( ThisActor, bShouldModifyLevel );

	// Invalidate the lighting cache in the Editor.  We need to check for GIsEditor as play has not begun in network game and objects get destroyed on switching levels
	if ( GIsEditor )
	{
		ThisActor->InvalidateLightingCache();
#if WITH_EDITOR
		GEngine->BroadcastLevelActorDeleted(ThisActor);
#endif
	}
		
	// Clean up the actor's components.
	ThisActor->UnregisterAllComponents();

	// Mark the actor and its direct components as pending kill.
	ThisActor->MarkPendingKill();
	ThisActor->MarkPackageDirty();
	ThisActor->MarkComponentsAsPendingKill();

	// Unregister the actor's tick function
	const bool bRegisterTickFunctions = false;
	const bool bIncludeComponents = true;
	ThisActor->RegisterAllActorTickFunctions(bRegisterTickFunctions, bIncludeComponents);

	// Return success.
	return true;
}
void USimpleConstructionScript::ExecuteScriptOnActor(AActor* Actor, const FTransform& RootTransform, bool bIsDefaultTransform)
{
	if(RootNodes.Num() > 0)
	{
		TSet<UActorComponent*> AllComponentsCreatedBySCS;
		TInlineComponentArray<UActorComponent*> InstancedComponents;
		for(auto NodeIt = RootNodes.CreateIterator(); NodeIt; ++NodeIt)
		{
			USCS_Node* RootNode = *NodeIt;
			if(RootNode != nullptr)
			{
				// Get all native scene components
				TInlineComponentArray<USceneComponent*> Components;
				Actor->GetComponents(Components);
				for (int32 Index = Components.Num()-1; Index >= 0; --Index)
				{
					USceneComponent* SceneComponent = Components[Index];
					if (SceneComponent->CreationMethod == EComponentCreationMethod::Instance)
					{
						Components.RemoveAt(Index);
					}
					else
					{
						// Handle the native sub-component of an instance component case
						USceneComponent* ParentSceneComponent = SceneComponent->GetTypedOuter<USceneComponent>();
						if (ParentSceneComponent && ParentSceneComponent->CreationMethod == EComponentCreationMethod::Instance)
						{
							Components.RemoveAt(Index);
						}
					}
				}

				// Get the native root component; if it's not set, the first native scene component will be used as root. This matches what's done in the SCS editor.
				USceneComponent* RootComponent = Actor->GetRootComponent();
				if(RootComponent == nullptr && Components.Num() > 0)
				{
					RootComponent = Components[0];
				}

				// If the root node specifies that it has a parent
				USceneComponent* ParentComponent = nullptr;
				if(RootNode->ParentComponentOrVariableName != NAME_None)
				{
					// Get the Actor class object
					UClass* ActorClass = Actor->GetClass();
					check(ActorClass != nullptr);

					// If the root node is parented to a "native" component (i.e. in the 'Components' array)
					if(RootNode->bIsParentComponentNative)
					{
						for(int32 CompIndex = 0; CompIndex < Components.Num(); ++CompIndex)
						{
							// If we found a match, remember the index
							if(Components[CompIndex]->GetFName() == RootNode->ParentComponentOrVariableName)
							{
								ParentComponent = Components[CompIndex];
								break;
							}
						}
					}
					else
					{
						// In the non-native case, the SCS node's variable name property is used as the parent identifier
						UObjectPropertyBase* Property = FindField<UObjectPropertyBase>(ActorClass, RootNode->ParentComponentOrVariableName);
						if(Property != nullptr)
						{
							// If we found a matching property, grab its value and use that as the parent for this node
							ParentComponent = Cast<USceneComponent>(Property->GetObjectPropertyValue_InContainer(Actor));
						}
					}
				}

				// Create the new component instance and any child components it may have
				UActorComponent* InstancedComponent = RootNode->ExecuteNodeOnActor(Actor, ParentComponent != nullptr ? ParentComponent : RootComponent, &RootTransform, bIsDefaultTransform);
				if(InstancedComponent != nullptr)
				{
					InstancedComponents.Add(InstancedComponent);
				}

				// get list of every component SCS created, in case some of them aren't in the attachment hierarchy any more (e.g. rigid bodies)
				TInlineComponentArray<USceneComponent*> ComponentsAfterSCS;
				Actor->GetComponents(ComponentsAfterSCS);
				for (USceneComponent* C : ComponentsAfterSCS)
				{
					if (Components.Contains(C) == false)
					{
						AllComponentsCreatedBySCS.Add(C);
					}
				}
			}
		}

		// Register all instanced SCS components once SCS execution has finished; sorted in order to register the scene component hierarchy first, followed by the remaining actor components (in case they happen to depend on something in the scene hierarchy)
		InstancedComponents.Sort([](const UActorComponent& A, const UActorComponent& B) { return A.IsA<USceneComponent>(); });
		for(auto InstancedComponent : InstancedComponents)
		{
			RegisterInstancedComponent(InstancedComponent);
		}

		// now that the instanced components in the attachment hierarchy are registered, register any other components that SCS made but aren't in the attachment hierarchy for whatever reason.
		for (auto C : AllComponentsCreatedBySCS)
		{
			if (C->IsRegistered() == false)
			{
				C->RegisterComponent();
			}
		}
	}
	else if(Actor->GetRootComponent() == NULL) // Must have a root component at the end of SCS, so if we don't have one already (from base class), create a SceneComponent now
	{
		USceneComponent* SceneComp = NewObject<USceneComponent>(Actor);
		SceneComp->SetFlags(RF_Transactional);
		SceneComp->CreationMethod = EComponentCreationMethod::SimpleConstructionScript;
		SceneComp->SetWorldTransform(RootTransform);
		Actor->SetRootComponent(SceneComp);
		SceneComp->RegisterComponent();
	}
}
void USimpleConstructionScript::FixupRootNodeParentReferences()
{
	// Get the BlueprintGeneratedClass that owns the SCS
	UClass* BPGeneratedClass = GetOwnerClass();
	if(BPGeneratedClass == NULL)
	{
		UE_LOG(LogBlueprint, Warning, TEXT("USimpleConstructionScript::FixupRootNodeParentReferences() - owner class is NULL; skipping."));
		// cannot do the rest of fixup without a BPGC
		return;
	}

	for (int32 NodeIndex=0; NodeIndex < RootNodes.Num(); ++NodeIndex)
	{
		// If this root node is parented to a native/inherited component template
		USCS_Node* RootNode = RootNodes[NodeIndex];
		if(RootNode->ParentComponentOrVariableName != NAME_None)
		{
			bool bWasFound = false;

			// If the node is parented to a native component
			if(RootNode->bIsParentComponentNative)
			{
				// Get the Blueprint class default object
				AActor* CDO = Cast<AActor>(BPGeneratedClass->GetDefaultObject(false));
				if(CDO != NULL)
				{
					// Look for the parent component in the CDO's components array
					TInlineComponentArray<UActorComponent*> Components;
					CDO->GetComponents(Components);

					for (auto CompIter = Components.CreateConstIterator(); CompIter && !bWasFound; ++CompIter)
					{
						UActorComponent* ComponentTemplate = *CompIter;
						bWasFound = ComponentTemplate->GetFName() == RootNode->ParentComponentOrVariableName;
					}
				}
				else 
				{ 
					// SCS and BGClass depends on each other (while their construction).
					// Class is not ready, so one have to break the dependency circle.
					continue;
				}
			}
			// Otherwise the node is parented to an inherited SCS node from a parent Blueprint
			else
			{
				// Get the Blueprint hierarchy
				TArray<const UBlueprintGeneratedClass*> ParentBPClassStack;
				const bool bErrorFree = UBlueprintGeneratedClass::GetGeneratedClassesHierarchy(BPGeneratedClass, ParentBPClassStack);

				// Find the parent Blueprint in the hierarchy
				for(int32 StackIndex = ParentBPClassStack.Num() - 1; StackIndex > 0; --StackIndex)
				{
					const UBlueprintGeneratedClass* ParentClass = ParentBPClassStack[StackIndex];
					if( ParentClass != NULL
						&& ParentClass->SimpleConstructionScript != NULL
						&& ParentClass->GetFName() == RootNode->ParentComponentOwnerClassName)
					{
						// Attempt to locate a match by searching all the nodes that belong to the parent Blueprint's SCS
						for (USCS_Node* ParentNode : ParentClass->SimpleConstructionScript->GetAllNodes())
						{
							if (ParentNode != nullptr && ParentNode->VariableName == RootNode->ParentComponentOrVariableName)
							{
								bWasFound = true;
								break;
							}
						}

						// We found a match; no need to continue searching the hierarchy
						break;
					}
				}
			}

			// Clear parent info if we couldn't find the parent component instance
			if(!bWasFound)
			{
				UE_LOG(LogBlueprint, Warning, TEXT("USimpleConstructionScript::FixupRootNodeParentReferences() - Couldn't find %s parent component '%s' for '%s' in BlueprintGeneratedClass '%s' (it may have been removed)"), RootNode->bIsParentComponentNative ? TEXT("native") : TEXT("inherited"), *RootNode->ParentComponentOrVariableName.ToString(), *RootNode->GetVariableName().ToString(), *BPGeneratedClass->GetName());

				RootNode->bIsParentComponentNative = false;
				RootNode->ParentComponentOrVariableName = NAME_None;
				RootNode->ParentComponentOwnerClassName = NAME_None;
			}
		}
	}

	// call this after we do the above ParentComponentOrVariableName fixup, 
	// because this operates differently for root nodes that have their 
	// ParentComponentOrVariableName field cleared
	//
	// repairs invalid scene hierarchies (like when this Blueprint has been 
	// reparented and there is no longer an inherited scene root... meaning one
	// of the scene component nodes here needs to be promoted)
	FixupSceneNodeHierarchy();
}