UStaticMeshComponent* UACarryObjectComponent::GetCarriedMeshComponent() { USceneComponent* ChildComp = GetChildComponent(0); if (ChildComp) { AActor* OwningActor = ChildComp->GetOwner(); if (OwningActor) { return Cast<UStaticMeshComponent>(OwningActor->GetComponentByClass(UStaticMeshComponent::StaticClass())); } } return nullptr; }
UActorComponent* AActor::AddComponent(FName TemplateName, bool bManualAttachment, const FTransform& RelativeTransform, const UObject* ComponentTemplateContext) { UActorComponent* Template = nullptr; UBlueprintGeneratedClass* BlueprintGeneratedClass = Cast<UBlueprintGeneratedClass>((ComponentTemplateContext != nullptr) ? ComponentTemplateContext->GetClass() : GetClass()); while(BlueprintGeneratedClass != nullptr) { Template = BlueprintGeneratedClass->FindComponentTemplateByName(TemplateName); if(nullptr != Template) { break; } BlueprintGeneratedClass = Cast<UBlueprintGeneratedClass>(BlueprintGeneratedClass->GetSuperClass()); } bool bIsSceneComponent = false; UActorComponent* NewActorComp = CreateComponentFromTemplate(Template); if(NewActorComp != nullptr) { // Call function to notify component it has been created NewActorComp->OnComponentCreated(); // The user has the option of doing attachment manually where they have complete control or via the automatic rule // that the first component added becomes the root component, with subsequent components attached to the root. USceneComponent* NewSceneComp = Cast<USceneComponent>(NewActorComp); if(NewSceneComp != nullptr) { if (!bManualAttachment) { if (RootComponent == nullptr) { RootComponent = NewSceneComp; } else { NewSceneComp->AttachTo(RootComponent); } } NewSceneComp->SetRelativeTransform(RelativeTransform); bIsSceneComponent = true; } // Register component, which will create physics/rendering state, now component is in correct position NewActorComp->RegisterComponent(); UWorld* World = GetWorld(); if (!bRunningUserConstructionScript && World && bIsSceneComponent) { UPrimitiveComponent* NewPrimitiveComponent = Cast<UPrimitiveComponent>(NewActorComp); if (NewPrimitiveComponent && ACullDistanceVolume::CanBeAffectedByVolumes(NewPrimitiveComponent)) { World->UpdateCullDistanceVolumes(this, NewPrimitiveComponent); } } } return NewActorComp; }
FTransform FMovieScene3DTransformSectionRecorder::GetTransformToRecord() { if(USceneComponent* SceneComponent = Cast<USceneComponent>(ObjectToRecord.Get())) { return SceneComponent->GetRelativeTransform(); } else if(AActor* Actor = Cast<AActor>(ObjectToRecord.Get())) { bool bCaptureWorldSpaceTransform = false; USceneComponent* RootComponent = Actor->GetRootComponent(); USceneComponent* AttachParent = RootComponent ? RootComponent->GetAttachParent() : nullptr; bWasAttached = AttachParent != nullptr; if (AttachParent) { // We capture world space transforms for actors if they're attached, but we're not recording the attachment parent bCaptureWorldSpaceTransform = !FSequenceRecorder::Get().FindRecording(AttachParent->GetOwner()); } return (bCaptureWorldSpaceTransform || !RootComponent) ? Actor->ActorToWorld() : RootComponent->GetRelativeTransform(); } return FTransform::Identity; }
USceneComponent* FComponentEditorUtils::FindClosestParentInList(UActorComponent* ChildComponent, const TArray<UActorComponent*>& ComponentList) { USceneComponent* ClosestParentComponent = nullptr; for (auto Component : ComponentList) { auto ChildAsScene = Cast<USceneComponent>(ChildComponent); auto SceneComponent = Cast<USceneComponent>(Component); if (ChildAsScene && SceneComponent) { // Check to see if any parent is also in the list USceneComponent* Parent = ChildAsScene->GetAttachParent(); while (Parent != nullptr) { if (ComponentList.Contains(Parent)) { ClosestParentComponent = SceneComponent; break; } Parent = Parent->GetAttachParent(); } } } return ClosestParentComponent; }
void UChildActorComponent::OnRegister() { Super::OnRegister(); if (ChildActor) { if (ChildActor->GetClass() != ChildActorClass) { DestroyChildActor(); CreateChildActor(); } else { ChildActorName = ChildActor->GetFName(); USceneComponent* ChildRoot = ChildActor->GetRootComponent(); if (ChildRoot && ChildRoot->GetAttachParent() != this) { // attach new actor to this component // we can't attach in CreateChildActor since it has intermediate Mobility set up // causing spam with inconsistent mobility set up // so moving Attach to happen in Register ChildRoot->AttachTo(this, NAME_None, EAttachLocation::SnapToTarget); } } } else if (ChildActorClass) { CreateChildActor(); } }
AActor* UVREditorMode::SpawnTransientSceneActor(TSubclassOf<AActor> ActorClass, const FString& ActorName, const bool bWithSceneComponent) const { const bool bWasWorldPackageDirty = GetWorld()->GetOutermost()->IsDirty(); // @todo vreditor: Needs respawn if world changes (map load, etc.) Will that always restart the editor mode anyway? FActorSpawnParameters ActorSpawnParameters; ActorSpawnParameters.Name = MakeUniqueObjectName( GetWorld(), ActorClass, *ActorName ); // @todo vreditor: Without this, SpawnActor() can return us an existing PendingKill actor of the same name! WTF? ActorSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; ActorSpawnParameters.ObjectFlags = EObjectFlags::RF_Transient; check( ActorClass != nullptr ); AActor* NewActor = GetWorld()->SpawnActor< AActor >( ActorClass, ActorSpawnParameters ); NewActor->SetActorLabel( ActorName ); if( bWithSceneComponent ) { // Give the new actor a root scene component, so we can attach multiple sibling components to it USceneComponent* SceneComponent = NewObject<USceneComponent>( NewActor ); NewActor->AddOwnedComponent( SceneComponent ); NewActor->SetRootComponent( SceneComponent ); SceneComponent->RegisterComponent(); } // Don't dirty the level file after spawning a transient actor if( !bWasWorldPackageDirty ) { GetWorld()->GetOutermost()->SetDirtyFlag( false ); } return NewActor; }
UActorComponent* UActorBlueprintLibrary::AttachComponentOfClass(UObject* WorldContextObject, TSubclassOf<UActorComponent> ComponentClass, AActor* Owner, FName ComponentName, USceneComponent* AttachTo, FName SocketName) { if (!Owner) { return nullptr; } UActorComponent* Component = NewObject<UActorComponent>(Owner, *ComponentClass, ComponentName); if (!Component) { return nullptr; } Component->RegisterComponent(); Component->OnComponentCreated(); USceneComponent* SceneComponent = Cast<USceneComponent>(Component); if (SceneComponent) { SceneComponent->SetWorldLocation(Owner->GetActorLocation()); SceneComponent->SetWorldRotation(Owner->GetActorRotation()); USceneComponent* AttachToComponent = AttachTo ? AttachTo : Owner->GetRootComponent(); SceneComponent->AttachToComponent(AttachToComponent, FAttachmentTransformRules::KeepWorldTransform, SocketName); } return Component; }
FVector FSCSEditorViewportClient::GetWidgetLocation() const { FVector Location = FVector::ZeroVector; AActor* PreviewActor = GetPreviewActor(); if(PreviewActor) { TArray<FSCSEditorTreeNodePtrType> SelectedNodes = BlueprintEditorPtr.Pin()->GetSelectedSCSEditorTreeNodes(); if(SelectedNodes.Num() > 0) { // Use the last selected item for the widget location USceneComponent* SceneComp = Cast<USceneComponent>(SelectedNodes.Last().Get()->FindComponentInstanceInActor(PreviewActor)); if( SceneComp ) { TSharedPtr<ISCSEditorCustomization> Customization = BlueprintEditorPtr.Pin()->CustomizeSCSEditor(SceneComp); FVector CustomLocation; if(Customization.IsValid() && Customization->HandleGetWidgetLocation(SceneComp, CustomLocation)) { Location = CustomLocation; } else { Location = SceneComp->GetComponentLocation(); } } } } return Location; }
static void GetActorsToIgnore( AActor* Actor, TSet< TWeakObjectPtr<AActor> >& ActorsToIgnore ) { if( !ActorsToIgnore.Contains( Actor ) ) { ActorsToIgnore.Add( Actor ); // We cannot snap to any attached children or actors in the same group as moving this actor will also move the children as we are snapping to them, // causing a cascading effect and unexpected results TArray<USceneComponent*>& AttachedChildren = Actor->GetRootComponent()->AttachChildren; for( int32 ChildIndex = 0; ChildIndex < AttachedChildren.Num(); ++ChildIndex ) { USceneComponent* Child = AttachedChildren[ChildIndex]; if( Child && Child->GetOwner() ) { ActorsToIgnore.Add( Child->GetOwner() ); } } AGroupActor* ParentGroup = AGroupActor::GetRootForActor(Actor, true, true); if( ParentGroup ) { TArray<AActor*> GroupActors; ParentGroup->GetGroupActors(GroupActors, true); for( int32 GroupActorIndex = 0; GroupActorIndex < GroupActors.Num(); ++GroupActorIndex ) { ActorsToIgnore.Add( GroupActors[GroupActorIndex] ); } } } }
void UChildActorComponent::OnRegister() { Super::OnRegister(); if (ChildActor) { if (ChildActor->GetClass() != ChildActorClass) { DestroyChildActor(); CreateChildActor(); } else { ChildActorName = ChildActor->GetFName(); USceneComponent* ChildRoot = ChildActor->GetRootComponent(); if (ChildRoot && ChildRoot->GetAttachParent() != this) { // attach new actor to this component // we can't attach in CreateChildActor since it has intermediate Mobility set up // causing spam with inconsistent mobility set up // so moving Attach to happen in Register ChildRoot->AttachToComponent(this, FAttachmentTransformRules::SnapToTargetNotIncludingScale); } // Ensure the components replication is correctly initialized SetIsReplicated(ChildActor->GetIsReplicated()); } } else if (ChildActorClass) { CreateChildActor(); } }
AActor* UACarryObjectComponent::GetCarriedActor() { USceneComponent* ChildComp = GetChildComponent(0); if (ChildComp) { return ChildComp->GetOwner(); } return nullptr; }
UActorComponent* FComponentEditorUtils::DuplicateComponent(UActorComponent* TemplateComponent) { check(TemplateComponent); UActorComponent* NewCloneComponent = nullptr; AActor* Actor = TemplateComponent->GetOwner(); if (!TemplateComponent->IsEditorOnly() && Actor) { Actor->Modify(); UClass* ComponentClass = TemplateComponent->GetClass(); FName NewComponentName = *FComponentEditorUtils::GenerateValidVariableName(ComponentClass, Actor); bool bKeepWorldLocationOnAttach = false; const bool bTemplateTransactional = TemplateComponent->HasAllFlags(RF_Transactional); TemplateComponent->SetFlags(RF_Transactional); NewCloneComponent = DuplicateObject<UActorComponent>(TemplateComponent, Actor, NewComponentName ); if (!bTemplateTransactional) { TemplateComponent->ClearFlags(RF_Transactional); } USceneComponent* NewSceneComponent = Cast<USceneComponent>(NewCloneComponent); if (NewSceneComponent) { // Ensure the clone doesn't think it has children NewSceneComponent->AttachChildren.Empty(); // If the clone is a scene component without an attach parent, attach it to the root (can happen when duplicating the root component) if (!NewSceneComponent->GetAttachParent()) { USceneComponent* RootComponent = Actor->GetRootComponent(); check(RootComponent); // ComponentToWorld is not a UPROPERTY, so make sure the clone has calculated it properly before attachment NewSceneComponent->UpdateComponentToWorld(); NewSceneComponent->AttachTo(RootComponent, NAME_None, EAttachLocation::KeepWorldPosition); } } NewCloneComponent->OnComponentCreated(); // Add to SerializedComponents array so it gets saved Actor->AddInstanceComponent(NewCloneComponent); // Register the new component NewCloneComponent->RegisterComponent(); // Rerun construction scripts Actor->RerunConstructionScripts(); } return NewCloneComponent; }
void FActorDropTarget::DetachActorFromParent(AActor* ChildActor) { USceneComponent* RootComp = ChildActor->GetRootComponent(); if (RootComp && RootComp->AttachParent) { AActor* OldParent = RootComp->AttachParent->GetOwner(); OldParent->Modify(); RootComp->DetachFromParent(true); ChildActor->SetFolderPath(OldParent->GetFolderPath()); } }
void FActorDropTarget::OnDrop(FDragDropPayload& DraggedObjects, UWorld& World, const FDragValidationInfo& ValidationInfo, TSharedRef<SWidget> DroppedOnWidget) { AActor* DropActor = Actor.Get(); if (!DropActor) { return; } FActorArray DraggedActors = DraggedObjects.Actors.GetValue(); FMessageLog EditorErrors("EditorErrors"); EditorErrors.NewPage(LOCTEXT("ActorAttachmentsPageLabel", "Actor attachment")); if (ValidationInfo.TooltipType == FActorDragDropGraphEdOp::ToolTip_CompatibleMultipleDetach || ValidationInfo.TooltipType == FActorDragDropGraphEdOp::ToolTip_CompatibleDetach) { const FScopedTransaction Transaction( LOCTEXT("UndoAction_DetachActors", "Detach actors") ); for (const auto& WeakActor : DraggedActors) { if (auto* DragActor = WeakActor.Get()) { DetachActorFromParent(DragActor); } } } else if (ValidationInfo.TooltipType == FActorDragDropGraphEdOp::ToolTip_CompatibleMultipleAttach || ValidationInfo.TooltipType == FActorDragDropGraphEdOp::ToolTip_CompatibleAttach) { // Show socket chooser if we have sockets to select //@TODO: Should create a menu for each component that contains sockets, or have some form of disambiguation within the menu (like a fully qualified path) // Instead, we currently only display the sockets on the root component USceneComponent* Component = DropActor->GetRootComponent(); if ((Component != NULL) && (Component->HasAnySockets())) { // Create the popup FSlateApplication::Get().PushMenu( DroppedOnWidget, SNew(SSocketChooserPopup) .SceneComponent( Component ) .OnSocketChosen_Static(&FActorDropTarget::PerformAttachment, Actor, MoveTemp(DraggedActors) ), FSlateApplication::Get().GetCursorPos(), FPopupTransitionEffect( FPopupTransitionEffect::TypeInPopup ) ); } else { PerformAttachment(NAME_None, Actor, MoveTemp(DraggedActors)); } } // Report errors EditorErrors.Notify(NSLOCTEXT("ActorAttachmentError", "AttachmentsFailed", "Attachments Failed!")); }
int32 GetAttachmentDepth(USceneComponent* Component) { int32 Depth = 0; USceneComponent* Parent = Component->GetAttachParent(); while (Parent) { ++Depth; Parent = Parent->GetAttachParent(); } return Depth; }
void FMovieScene3DConstraintTrackInstance::SaveState(const TArray<UObject*>& RuntimeObjects, IMovieScenePlayer& Player, FMovieSceneSequenceInstance& SequenceInstance) { for (int32 ObjIndex = 0; ObjIndex < RuntimeObjects.Num(); ++ObjIndex) { USceneComponent* SceneComponent = MovieSceneHelpers::SceneComponentFromRuntimeObject(RuntimeObjects[ObjIndex]); if (SceneComponent != nullptr) { if (InitTransformMap.Find(RuntimeObjects[ObjIndex]) == nullptr) { InitTransformMap.Add(RuntimeObjects[ObjIndex], SceneComponent->GetRelativeTransform()); } } } }
void UActorRecording::GetSceneComponents(TArray<USceneComponent*>& OutArray, bool bIncludeNonCDO/*=true*/) { // it is not enough to just go through the owned components array here // we need to traverse the scene component hierarchy as well, as some components may be // owned by other actors (e.g. for pooling) and some may not be part of the hierarchy if(GetActorToRecord() != nullptr) { USceneComponent* RootComponent = GetActorToRecord()->GetRootComponent(); if(RootComponent) { // note: GetChildrenComponents clears array! RootComponent->GetChildrenComponents(true, OutArray); OutArray.Add(RootComponent); } // add owned components that are *not* part of the hierarchy TInlineComponentArray<USceneComponent*> OwnedComponents(GetActorToRecord()); for(USceneComponent* OwnedComponent : OwnedComponents) { check(OwnedComponent); if(OwnedComponent->GetAttachParent() == nullptr && OwnedComponent != RootComponent) { OutArray.Add(OwnedComponent); } } if(!bIncludeNonCDO) { AActor* CDO = Cast<AActor>(GetActorToRecord()->GetClass()->GetDefaultObject()); auto ShouldRemovePredicate = [&](UActorComponent* PossiblyRemovedComponent) { // try to find a component with this name in the CDO for (UActorComponent* SearchComponent : CDO->GetComponents()) { if (SearchComponent->GetClass() == PossiblyRemovedComponent->GetClass() && SearchComponent->GetFName() == PossiblyRemovedComponent->GetFName()) { return false; } } // remove if its not found return true; }; OutArray.RemoveAllSwap(ShouldRemovePredicate); } } }
void AHunterProjectile::MoveInDirection(const FVector &direction) { m_velocity = direction * m_projectileVelocity; USceneComponent *hopefullySprite = GetRootComponent()->GetChildComponent(0); if (hopefullySprite != nullptr) { FRotator thisRotation = hopefullySprite->RelativeRotation; FRotator directionRotator = direction.Rotation(); thisRotation.Yaw = directionRotator.Yaw; hopefullySprite->SetRelativeRotation(thisRotation); } }
void FDeferRegisterStaticComponents::RegisterComponents(AActor* Actor) { TArray<FDeferredComponentInfo>* ActorComponentsToRegister = ComponentsToRegister.Find(Actor); if (ActorComponentsToRegister) { for (int32 ComponentIndex = 0; ComponentIndex < ActorComponentsToRegister->Num(); ++ComponentIndex) { const FDeferredComponentInfo& SavedInfo = (*ActorComponentsToRegister)[ComponentIndex]; USceneComponent* Component = SavedInfo.Component; // Restore saved mobility just before registering this component. Component->Mobility = SavedInfo.SavedMobility; Component->RegisterComponent(); } ComponentsToRegister.Remove(Actor); } }
USceneComponent * ABomb::GetComponent(USceneComponent *parent, const FString& childLabel) { if (!parent) return NULL; USceneComponent *child = NULL; for (int i=0; i<parent->GetNumChildrenComponents(); i++) { child = parent->GetChildComponent(i); if (child && child->GetName() == childLabel) break; } return child; }
float APawn::GetDefaultHalfHeight() const { USceneComponent* DefaultRoot = GetClass()->GetDefaultObject<APawn>()->RootComponent; if (DefaultRoot) { float Radius, HalfHeight; DefaultRoot->UpdateBounds(); // Since it's the default object, it wouldn't have been registered to ever do this. DefaultRoot->CalcBoundingCylinder(Radius, HalfHeight); return HalfHeight; } else { // This will probably fail to return anything useful, since default objects won't have registered components, // but at least it will spit out a warning if so. return GetClass()->GetDefaultObject<APawn>()->GetSimpleCollisionHalfHeight(); } }
void FComponentEditorUtils::AdjustComponentDelta(USceneComponent* Component, FVector& Drag, FRotator& Rotation) { USceneComponent* ParentSceneComp = Component->GetAttachParent(); if (ParentSceneComp) { const FTransform ParentToWorldSpace = ParentSceneComp->GetSocketTransform(Component->AttachSocketName); if (!Component->bAbsoluteLocation) { Drag = ParentToWorldSpace.Inverse().TransformVector(Drag); } if (!Component->bAbsoluteRotation) { Rotation = ( ParentToWorldSpace.Inverse().GetRotation() * Rotation.Quaternion() * ParentToWorldSpace.GetRotation() ).Rotator(); } } }
PyObject *py_ue_add_actor_root_component(ue_PyUObject * self, PyObject * args) { ue_py_check(self); PyObject *obj; char *name; if (!PyArg_ParseTuple(args, "Os:add_actor_root_component", &obj, &name)) { return NULL; } if (!self->ue_object->IsA<AActor>()) { return PyErr_Format(PyExc_Exception, "uobject is not an AActor"); } AActor *actor = (AActor *)self->ue_object; if (!ue_is_pyuobject(obj)) { return PyErr_Format(PyExc_Exception, "argument is not a UObject"); } ue_PyUObject *py_obj = (ue_PyUObject *)obj; if (!py_obj->ue_object->IsA<UClass>()) { return PyErr_Format(PyExc_Exception, "argument is not a class"); } USceneComponent *component = NewObject<USceneComponent>(actor, (UClass *)py_obj->ue_object, FName(UTF8_TO_TCHAR(name))); if (!component) return PyErr_Format(PyExc_Exception, "unable to create component"); actor->SetRootComponent(component); if (actor->GetWorld()) { component->RegisterComponent(); } PyObject *ret = (PyObject *)ue_get_python_wrapper(component); if (!ret) return PyErr_Format(PyExc_Exception, "uobject is in invalid state"); Py_INCREF(ret); return ret; }
void AActor::SetFolderPath(const FName& NewFolderPath, bool bDetachFromParent) { // Detach the actor if it is attached USceneComponent* RootComp = GetRootComponent(); const bool bIsAttached = RootComp && RootComp->AttachParent; if (NewFolderPath == FolderPath && !bIsAttached) { return; } Modify(); FName OldPath = FolderPath; FolderPath = NewFolderPath; // Detach the actor if it is attached if (bIsAttached && bDetachFromParent) { AActor* OldParentActor = RootComp->AttachParent->GetOwner(); OldParentActor->Modify(); RootComp->DetachFromParent(true); } if (GEngine) { GEngine->BroadcastLevelActorFolderChanged(this, OldPath); } //recursively change folder path for children (but do not detach so they remain as child) if(RootComp) { for(auto ChildSceneComponent : RootComp->AttachChildren) { AActor* ChildActor = ChildSceneComponent ? ChildSceneComponent->GetOwner() : nullptr; if(ChildActor) { ChildActor->SetFolderPath(NewFolderPath, false); } } } }
void UChildActorComponent::ApplyComponentInstanceData(FChildActorComponentInstanceData* ChildActorInstanceData, const ECacheApplyPhase CacheApplyPhase) { check(ChildActorInstanceData); ChildActorName = ChildActorInstanceData->ChildActorName; if (ChildActor) { // Only rename if it is safe to if(ChildActorName != NAME_None) { const FString ChildActorNameString = ChildActorName.ToString(); if (ChildActor->Rename(*ChildActorNameString, nullptr, REN_Test)) { ChildActor->Rename(*ChildActorNameString, nullptr, REN_DoNotDirty | (IsLoading() ? REN_ForceNoResetLoaders : REN_None)); } } if (ChildActorInstanceData->ComponentInstanceData) { ChildActorInstanceData->ComponentInstanceData->ApplyToActor(ChildActor, CacheApplyPhase); } USceneComponent* ChildActorRoot = ChildActor->GetRootComponent(); if (ChildActorRoot) { for (const auto& AttachInfo : ChildActorInstanceData->AttachedActors) { AActor* AttachedActor = AttachInfo.Actor.Get(); if (AttachedActor) { USceneComponent* AttachedRootComponent = AttachedActor->GetRootComponent(); if (AttachedRootComponent) { AttachedActor->DetachRootComponentFromParent(); AttachedRootComponent->AttachToComponent(ChildActorRoot, FAttachmentTransformRules::KeepWorldTransform, AttachInfo.SocketName); AttachedRootComponent->SetRelativeTransform(AttachInfo.RelativeTransform); AttachedRootComponent->UpdateComponentToWorld(); } } } } } }
void FMovieScene3DAttachTrackInstance::UpdateConstraint( float Position, const TArray<TWeakObjectPtr<UObject>>& RuntimeObjects, AActor* Actor, UMovieScene3DConstraintSection* ConstraintSection ) { FVector Translation; FRotator Rotation; UMovieScene3DAttachSection* AttachSection = CastChecked<UMovieScene3DAttachSection>(ConstraintSection); for( int32 ObjIndex = 0; ObjIndex < RuntimeObjects.Num(); ++ObjIndex ) { USceneComponent* SceneComponent = MovieSceneHelpers::SceneComponentFromRuntimeObject(RuntimeObjects[ObjIndex].Get()); if (SceneComponent != nullptr) { AttachSection->Eval(SceneComponent, Position, Actor, Translation, Rotation); // Set the relative translation and rotation. Note they are set once instead of individually to avoid a redundant component transform update. SceneComponent->SetRelativeLocationAndRotation(Translation, Rotation); } } }
bool ActorHasParentInGroup(const TArray<class AActor*> &GroupActors, const AActor* Actor) { check(Actor); // Check that we've not got a parent attachment within the group. USceneComponent *Curr = Actor->GetRootComponent(); for(int32 OtherIndex=0; OtherIndex<GroupActors.Num(); ++OtherIndex) { const AActor* OtherActor = GroupActors[OtherIndex]; if( OtherActor != NULL && OtherActor != Actor ) { USceneComponent *Other = OtherActor->GetRootComponent(); if( Curr->IsAttachedTo( Other ) ) { // We do have parent so don't apply the delta - our parent object will apply it instead. return true; } } } return false; }
void FMovieScene3DConstraintTrackInstance::RestoreState(const TArray<UObject*>& RuntimeObjects, IMovieScenePlayer& Player, FMovieSceneSequenceInstance& SequenceInstance) { for (int32 ObjIndex = 0; ObjIndex < RuntimeObjects.Num(); ++ObjIndex) { if (!IsValid(RuntimeObjects[ObjIndex])) { continue; } USceneComponent* SceneComponent = MovieSceneHelpers::SceneComponentFromRuntimeObject(RuntimeObjects[ObjIndex]); if (SceneComponent != nullptr) { FTransform *Transform = InitTransformMap.Find(RuntimeObjects[ObjIndex]); if (Transform != nullptr) { SceneComponent->SetRelativeTransform(*Transform); } } } }
void FMovieScene3DTransformTrackInstance::Update( float Position, float LastPosition, const TArray<UObject*>& RuntimeObjects, class IMovieScenePlayer& Player ) { FVector Translation; FRotator Rotation; FVector Scale; bool bHasTranslationKeys = false; bool bHasRotationKeys = false; bool bHasScaleKeys = false; if( TransformTrack->Eval( Position, LastPosition, Translation, Rotation, Scale, bHasTranslationKeys, bHasRotationKeys, bHasScaleKeys ) ) { for( int32 ObjIndex = 0; ObjIndex < RuntimeObjects.Num(); ++ObjIndex ) { UObject* Object = RuntimeObjects[ObjIndex]; AActor* Actor = Cast<AActor>( Object ); USceneComponent* SceneComponent = NULL; if( Actor && Actor->GetRootComponent() ) { // If there is an actor, modify its root component SceneComponent = Actor->GetRootComponent(); } else { // No actor was found. Attempt to get the object as a component in the case that we are editing them directly. SceneComponent = Cast<USceneComponent>( Object ); } // Set the relative translation and rotation. Note they are set once instead of individually to avoid a redundant component transform update. SceneComponent->SetRelativeLocationAndRotation( bHasTranslationKeys ? Translation : SceneComponent->RelativeLocation, bHasRotationKeys ? Rotation : SceneComponent->RelativeRotation ); if( bHasScaleKeys ) { SceneComponent->SetRelativeScale3D( Scale ); } } } }
void FComponentEditorUtils::AdjustComponentDelta(USceneComponent* Component, FVector& Drag, FRotator& Rotation) { USceneComponent* ParentSceneComp = Component->GetAttachParent(); if (ParentSceneComp) { const FTransform ParentToWorldSpace = ParentSceneComp->GetSocketTransform(Component->AttachSocketName); if (!Component->bAbsoluteLocation) { //transform the drag vector in relative to the parent transform Drag = ParentToWorldSpace.InverseTransformVectorNoScale(Drag); //Now that we have a global drag we can apply the parent scale Drag = Drag * ParentToWorldSpace.Inverse().GetScale3D(); } if (!Component->bAbsoluteRotation) { Rotation = ( ParentToWorldSpace.Inverse().GetRotation() * Rotation.Quaternion() * ParentToWorldSpace.GetRotation() ).Rotator(); } } }