void AActor::PreEditUndo() { // Since child actor components will rebuild themselves get rid of the Actor before we make changes TInlineComponentArray<UChildActorComponent*> ChildActorComponents; GetComponents(ChildActorComponents); for (UChildActorComponent* ChildActorComponent : ChildActorComponents) { if (ChildActorComponent->IsCreatedByConstructionScript()) { ChildActorComponent->DestroyChildActor(); } } // let navigation system know to not care about this actor anymore UNavigationSystem::ClearNavOctreeAll(this); Super::PreEditUndo(); }
static unsigned BuildNativeDeclaration( D3D11_SO_DECLARATION_ENTRY nativeDeclaration[], unsigned nativeDeclarationCount, const GeometryShader::StreamOutputInitializers& soInitializers) { auto finalCount = std::min(nativeDeclarationCount, soInitializers._outputElementCount); for (unsigned c=0; c<finalCount; ++c) { auto& ele = soInitializers._outputElements[c]; nativeDeclaration[c].Stream = 0; nativeDeclaration[c].SemanticName = ele._semanticName.c_str(); nativeDeclaration[c].SemanticIndex = ele._semanticIndex; nativeDeclaration[c].StartComponent = 0; nativeDeclaration[c].ComponentCount = (BYTE)GetComponentCount(GetComponents(ele._nativeFormat)); // hack -- treat "R16G16B16A16_FLOAT" as a 3 dimensional vector if (ele._nativeFormat == NativeFormat::Enum::R16G16B16A16_FLOAT) nativeDeclaration[c].ComponentCount = 3; nativeDeclaration[c].OutputSlot = (BYTE)ele._inputSlot; assert(nativeDeclaration[c].OutputSlot < soInitializers._outputBufferCount); } return finalCount; }
//------------------------------------------------------------- // Task : Append a subdirectory 2 path's directory //------------------------------------------------------------- void CPath::AppendDirectory(const char * lpszSubDirectory) { std::string Drive; std::string Directory; std::string SubDirectory =lpszSubDirectory; std::string Name; std::string Extension; if(SubDirectory.empty()) return; // Strip out any preceeding backslash StripLeadingBackslash(SubDirectory); EnsureTrailingBackslash(SubDirectory); GetComponents(&Drive,&Directory,&Name,&Extension); EnsureTrailingBackslash(Directory); Directory +=SubDirectory; SetComponents(Drive.c_str(),Directory.c_str(),Name.c_str(),Extension.c_str()); }
//* Destroys the constructed components. void AActor::DestroyConstructedComponents() { // Remove all existing components TArray<UActorComponent*> PreviouslyAttachedComponents; GetComponents(PreviouslyAttachedComponents); for (int32 i = 0; i < PreviouslyAttachedComponents.Num(); i++) { UActorComponent*& Component = PreviouslyAttachedComponents[i]; if (Component && Component->bCreatedByConstructionScript) { 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); } } }
//----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- void CDmeSingleIndexedComponent::Add( const CDmeSingleIndexedComponent &rhs ) { int nLhs = Count(); const int nRhs = rhs.Count(); int l = 0; int r = 0; if ( IsComplete() ) { if ( rhs.IsComplete() && nRhs > nLhs ) { m_CompleteCount.Set( nRhs ); } else { while ( r < nRhs ) { if ( rhs.m_Components[ r ] >= nLhs ) { // Got one that's greater than the complete count of this one CUtlVector< int > newComponents; newComponents.EnsureCapacity( nLhs + nRhs - r ); CUtlVector< float > newWeights; newWeights.EnsureCapacity( nLhs + nRhs - r ); GetComponents( newComponents, newWeights ); while ( r < nRhs ) { newComponents.AddToTail( rhs.m_Components[ r ] ); newWeights.AddToTail( rhs.m_Weights[ r ] ); ++r; } m_Components.CopyArray( newComponents.Base(), newComponents.Count() ); m_Weights.CopyArray( newWeights.Base(), newWeights.Count() ); m_CompleteCount.Set( 0 ); m_bComplete.Set( false ); break; } ++r; } } } else { CUtlVector< int > newComponents; newComponents.EnsureCapacity( nLhs + nRhs * 0.5 ); // Just an estimate assuming 50% of the components in rhs aren't in lhs CUtlVector< float > newWeights; newWeights.EnsureCapacity( nLhs + nRhs * 0.5 ); // Just an estimate while ( l < nLhs || r < nRhs ) { while ( l < nLhs && ( r >= nRhs || m_Components[ l ] < rhs.m_Components[ r ] ) ) { newComponents.AddToTail( m_Components[ l ] ); newWeights.AddToTail( m_Weights[ l ] ); ++l; } // In RHS but not LHS while ( r < nRhs && ( l >= nLhs || m_Components[ l ] > rhs.m_Components[ r ] ) ) { newComponents.AddToTail( rhs.m_Components[ r ] ); newWeights.AddToTail( rhs.m_Weights[ r ] ); ++r; } // In Both LHS & RHS while ( l < nLhs && r < nRhs && m_Components[ l ] == rhs.m_Components[ r ] ) { newComponents.AddToTail( m_Components[ l ] ); newWeights.AddToTail( m_Weights[ l ] ); ++l; ++r; } } m_Components.CopyArray( newComponents.Base(), newComponents.Count() ); m_Weights.CopyArray( newWeights.Base(), newWeights.Count() ); } m_CompleteCount.Set( 0 ); m_bComplete.Set( false ); }
void AActor::ExecuteConstruction(const FTransform& Transform, const FComponentInstanceDataCache* InstanceDataCache, bool bIsDefaultTransform) { check(!IsPendingKill()); check(!HasAnyFlags(RF_BeginDestroyed|RF_FinishDestroyed)); // ensure that any existing native root component gets this new transform // we can skip this in the default case as the given transform will be the root component's transform if (RootComponent && !bIsDefaultTransform) { RootComponent->SetWorldTransform(Transform); } // Generate the parent blueprint hierarchy for this actor, so we can run all the construction scripts sequentially TArray<const UBlueprintGeneratedClass*> ParentBPClassStack; const bool bErrorFree = UBlueprintGeneratedClass::GetGeneratedClassesHierarchy(GetClass(), ParentBPClassStack); // If this actor has a blueprint lineage, go ahead and run the construction scripts from least derived to most if( (ParentBPClassStack.Num() > 0) ) { if( bErrorFree ) { // Prevent user from spawning actors in User Construction Script TGuardValue<bool> AutoRestoreISCS(GetWorld()->bIsRunningConstructionScript, true); for( int32 i = ParentBPClassStack.Num() - 1; i >= 0; i-- ) { const UBlueprintGeneratedClass* CurrentBPGClass = ParentBPClassStack[i]; check(CurrentBPGClass); if(CurrentBPGClass->SimpleConstructionScript) { CurrentBPGClass->SimpleConstructionScript->ExecuteScriptOnActor(this, Transform, bIsDefaultTransform); } // Now that the construction scripts have been run, we can create timelines and hook them up CurrentBPGClass->CreateComponentsForActor(this); } // If we passed in cached data, we apply it now, so that the UserConstructionScript can use the updated values if(InstanceDataCache) { InstanceDataCache->ApplyToActor(this, ECacheApplyPhase::PostSimpleConstructionScript); } #if WITH_EDITOR bool bDoUserConstructionScript; GConfig->GetBool(TEXT("Kismet"), TEXT("bTurnOffEditorConstructionScript"), bDoUserConstructionScript, GEngineIni); if (!GIsEditor || !bDoUserConstructionScript) #endif { // Then run the user script, which is responsible for calling its own super, if desired ProcessUserConstructionScript(); } // Since re-run construction scripts will never be run and we want to keep dynamic spawning fast, don't spend time // determining the UCS modified properties in game worlds if (!GetWorld()->IsGameWorld()) { for (UActorComponent* Component : GetComponents()) { if (Component) { Component->DetermineUCSModifiedProperties(); } } } // Bind any delegates on components ((UBlueprintGeneratedClass*)GetClass())->BindDynamicDelegates(this); // We have a BP stack, we must have a UBlueprintGeneratedClass... // Apply any cached data procedural components // @TODO Don't re-apply to components we already applied to above if (InstanceDataCache) { InstanceDataCache->ApplyToActor(this, ECacheApplyPhase::PostUserConstructionScript); } } else { // Disaster recovery mode; create a dummy billboard component to retain the actor location // until the compile error can be fixed if (RootComponent == NULL) { UBillboardComponent* BillboardComponent = NewObject<UBillboardComponent>(this); BillboardComponent->SetFlags(RF_Transactional); BillboardComponent->CreationMethod = EComponentCreationMethod::SimpleConstructionScript; #if WITH_EDITOR BillboardComponent->Sprite = (UTexture2D*)(StaticLoadObject(UTexture2D::StaticClass(), NULL, TEXT("/Engine/EditorResources/BadBlueprintSprite.BadBlueprintSprite"), NULL, LOAD_None, NULL)); #endif BillboardComponent->SetRelativeTransform(Transform); SetRootComponent(BillboardComponent); FinishAndRegisterComponent(BillboardComponent); } } } GetWorld()->UpdateCullDistanceVolumes(this); // Now run virtual notification OnConstruction(Transform); }
void AActor::RerunConstructionScripts() { checkf(!HasAnyFlags(RF_ClassDefaultObject), TEXT("RerunConstructionScripts should never be called on a CDO as it can mutate the transient data on the CDO which then propagates to instances!")); FEditorScriptExecutionGuard ScriptGuard; // don't allow (re)running construction scripts on dying actors bool bAllowReconstruction = !IsPendingKill() && !HasAnyFlags(RF_BeginDestroyed|RF_FinishDestroyed); #if WITH_EDITOR if(bAllowReconstruction && GIsEditor) { // Generate the blueprint hierarchy for this actor TArray<UBlueprint*> ParentBPStack; bAllowReconstruction = UBlueprint::GetBlueprintHierarchyFromClass(GetClass(), ParentBPStack); if(bAllowReconstruction) { for(int i = ParentBPStack.Num() - 1; i > 0 && bAllowReconstruction; --i) { const UBlueprint* ParentBP = ParentBPStack[i]; if(ParentBP && ParentBP->bBeingCompiled) { // don't allow (re)running construction scripts if a parent BP is being compiled bAllowReconstruction = false; } } } } #endif if(bAllowReconstruction) { // Set global flag to let system know we are reconstructing blueprint instances TGuardValue<bool> GuardTemplateNameFlag(GIsReconstructingBlueprintInstances, true); // Temporarily suspend the undo buffer; we don't need to record reconstructed component objects into the current transaction ITransaction* CurrentTransaction = GUndo; GUndo = NULL; // Create cache to store component data across rerunning construction scripts #if WITH_EDITOR FActorTransactionAnnotation* ActorTransactionAnnotation = CurrentTransactionAnnotation.Get(); #endif FComponentInstanceDataCache* InstanceDataCache; FTransform OldTransform = FTransform::Identity; FName SocketName; AActor* Parent = NULL; USceneComponent* ParentComponent = NULL; bool bUseRootComponentProperties = true; // Struct to store info about attached actors struct FAttachedActorInfo { AActor* AttachedActor; FName AttachedToSocket; bool bSetRelativeTransform; FTransform RelativeTransform; }; // Save info about attached actors TArray<FAttachedActorInfo> AttachedActorInfos; #if WITH_EDITOR if (ActorTransactionAnnotation) { InstanceDataCache = &ActorTransactionAnnotation->ComponentInstanceData; if (ActorTransactionAnnotation->bRootComponentDataCached) { OldTransform = ActorTransactionAnnotation->RootComponentData.Transform; Parent = ActorTransactionAnnotation->RootComponentData.AttachedParentInfo.Actor.Get(); if (Parent) { USceneComponent* AttachParent = ActorTransactionAnnotation->RootComponentData.AttachedParentInfo.AttachParent.Get(); ParentComponent = (AttachParent ? AttachParent : FindObjectFast<USceneComponent>(Parent, ActorTransactionAnnotation->RootComponentData.AttachedParentInfo.AttachParentName)); SocketName = ActorTransactionAnnotation->RootComponentData.AttachedParentInfo.SocketName; DetachRootComponentFromParent(); } for (const auto& CachedAttachInfo : ActorTransactionAnnotation->RootComponentData.AttachedToInfo) { AActor* AttachedActor = CachedAttachInfo.Actor.Get(); if (AttachedActor) { FAttachedActorInfo Info; Info.AttachedActor = AttachedActor; Info.AttachedToSocket = CachedAttachInfo.SocketName; Info.bSetRelativeTransform = true; Info.RelativeTransform = CachedAttachInfo.RelativeTransform; AttachedActorInfos.Add(Info); AttachedActor->DetachRootComponentFromParent(); } } bUseRootComponentProperties = false; } } else #endif { InstanceDataCache = new FComponentInstanceDataCache(this); // If there are attached objects detach them and store the socket names TArray<AActor*> AttachedActors; GetAttachedActors(AttachedActors); for (AActor* AttachedActor : AttachedActors) { USceneComponent* EachRoot = AttachedActor->GetRootComponent(); // If the component we are attached to is about to go away... if (EachRoot && EachRoot->AttachParent && EachRoot->AttachParent->IsCreatedByConstructionScript()) { // Save info about actor to reattach FAttachedActorInfo Info; Info.AttachedActor = AttachedActor; Info.AttachedToSocket = EachRoot->AttachSocketName; Info.bSetRelativeTransform = false; AttachedActorInfos.Add(Info); // Now detach it AttachedActor->Modify(); EachRoot->DetachFromParent(true); } } } if (bUseRootComponentProperties && RootComponent != nullptr) { // Do not need to detach if root component is not going away if (RootComponent->AttachParent != NULL && RootComponent->IsCreatedByConstructionScript()) { Parent = RootComponent->AttachParent->GetOwner(); // Root component should never be attached to another component in the same actor! if (Parent == this) { UE_LOG(LogActor, Warning, TEXT("RerunConstructionScripts: RootComponent (%s) attached to another component in this Actor (%s)."), *RootComponent->GetPathName(), *Parent->GetPathName()); Parent = NULL; } ParentComponent = RootComponent->AttachParent; SocketName = RootComponent->AttachSocketName; //detach it to remove any scaling RootComponent->DetachFromParent(true); } OldTransform = RootComponent->ComponentToWorld; OldTransform.SetTranslation(RootComponent->GetComponentLocation()); // take into account any custom location } #if WITH_EDITOR // Save the current construction script-created components by name TMap<const FName, UObject*> DestroyedComponentsByName; TInlineComponentArray<UActorComponent*> PreviouslyAttachedComponents; GetComponents(PreviouslyAttachedComponents); for (auto Component : PreviouslyAttachedComponents) { if (Component) { if (Component->IsCreatedByConstructionScript()) { DestroyedComponentsByName.Add(Component->GetFName(), Component); } else { UActorComponent* OuterComponent = Component->GetTypedOuter<UActorComponent>(); while (OuterComponent) { if (OuterComponent->IsCreatedByConstructionScript()) { DestroyedComponentsByName.Add(Component->GetFName(), Component); break; } OuterComponent = OuterComponent->GetTypedOuter<UActorComponent>(); } } } } #endif // Destroy existing components DestroyConstructedComponents(); // Reset random streams ResetPropertiesForConstruction(); // Exchange net roles before running construction scripts UWorld *OwningWorld = GetWorld(); if (OwningWorld && !OwningWorld->IsServer()) { ExchangeNetRoles(true); } // Run the construction scripts ExecuteConstruction(OldTransform, InstanceDataCache); if(Parent) { USceneComponent* ChildRoot = GetRootComponent(); if (ParentComponent == NULL) { ParentComponent = Parent->GetRootComponent(); } if (ChildRoot != NULL && ParentComponent != NULL) { ChildRoot->AttachTo(ParentComponent, SocketName, EAttachLocation::KeepWorldPosition); } } // If we had attached children reattach them now - unless they are already attached for(FAttachedActorInfo& Info : AttachedActorInfos) { // If this actor is no longer attached to anything, reattach if (!Info.AttachedActor->IsPendingKill() && Info.AttachedActor->GetAttachParentActor() == NULL) { USceneComponent* ChildRoot = Info.AttachedActor->GetRootComponent(); if (ChildRoot && ChildRoot->AttachParent != RootComponent) { ChildRoot->AttachTo(RootComponent, Info.AttachedToSocket, EAttachLocation::KeepWorldPosition); if (Info.bSetRelativeTransform) { ChildRoot->SetRelativeTransform(Info.RelativeTransform); } ChildRoot->UpdateComponentToWorld(); } } } // Restore the undo buffer GUndo = CurrentTransaction; #if WITH_EDITOR // Create the mapping of old->new components and notify the editor of the replacements TMap<UObject*, UObject*> OldToNewComponentMapping; TInlineComponentArray<UActorComponent*> NewComponents; GetComponents(NewComponents); for (auto NewComp : NewComponents) { const FName NewCompName = NewComp->GetFName(); if (DestroyedComponentsByName.Contains(NewCompName)) { OldToNewComponentMapping.Add(DestroyedComponentsByName[NewCompName], NewComp); } } if (GEditor && (OldToNewComponentMapping.Num() > 0)) { GEditor->NotifyToolsOfObjectReplacement(OldToNewComponentMapping); } if (ActorTransactionAnnotation) { CurrentTransactionAnnotation = NULL; } else #endif { delete InstanceDataCache; } } }
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; } } }
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); }
std::string CPath::GetExtension(void) const { std::string rExtension; GetComponents(NULL,NULL,NULL,&rExtension); return rExtension; }
//------------------------------------------------------------- // Task : Get file extension from path //------------------------------------------------------------- void CPath::GetExtension(std::string& rExtension) const { GetComponents(NULL,NULL,NULL,&rExtension); }
std::string CPath::GetName(void) const { std::string rName; GetComponents(NULL,NULL,&rName); return rName; }
//------------------------------------------------------------- // Task : Get filename from path //------------------------------------------------------------- void CPath::GetName(std::string& rName) const { GetComponents(NULL,NULL,&rName); }
std::string CPath::GetDirectory(void) const { std::string rDirectory; GetComponents(NULL,&rDirectory); return rDirectory; }
//------------------------------------------------------------- // Task : Get directory from path //------------------------------------------------------------- void CPath::GetDirectory(std::string& rDirectory) const { GetComponents(NULL,&rDirectory); }
void ACameraRig_Rail::UpdatePreviewMeshes() { if (RailSplineComponent) { if (PreviewRailStaticMesh) { int32 const NumSplinePoints = RailSplineComponent->GetNumberOfSplinePoints(); int32 const NumNeededPreviewMeshes = NumSplinePoints - 1; // make sure our preview mesh array is correctly sized and populated { int32 const NumExistingPreviewMeshes = PreviewRailMeshSegments.Num(); if (NumExistingPreviewMeshes > NumNeededPreviewMeshes) { // we have too many meshes, remove some int32 const NumToRemove = NumExistingPreviewMeshes - NumNeededPreviewMeshes; for (int Idx = 0; Idx < NumToRemove; ++Idx) { USplineMeshComponent* const ElementToRemove = PreviewRailMeshSegments.Pop(); ElementToRemove->UnregisterComponent(); } } else if (NumExistingPreviewMeshes < NumNeededPreviewMeshes) { int32 const NumToAdd = NumNeededPreviewMeshes - NumExistingPreviewMeshes; for (int32 Idx = 0; Idx < NumToAdd; ++Idx) { USplineMeshComponent* PreviewMesh = CreateSplinePreviewSegment(); PreviewRailMeshSegments.Add(PreviewMesh); } } check(PreviewRailMeshSegments.Num() == NumNeededPreviewMeshes); } for (int PtIdx = 0; PtIdx < NumSplinePoints - 1; ++PtIdx) { FVector StartLoc, StartTangent, EndLoc, EndTangent; RailSplineComponent->GetLocationAndTangentAtSplinePoint(PtIdx, StartLoc, StartTangent, ESplineCoordinateSpace::Local); RailSplineComponent->GetLocationAndTangentAtSplinePoint(PtIdx + 1, EndLoc, EndTangent, ESplineCoordinateSpace::Local); USplineMeshComponent* const SplineMeshComp = PreviewRailMeshSegments[PtIdx]; if (SplineMeshComp) { SplineMeshComp->SetForwardAxis(ESplineMeshAxis::Z); SplineMeshComp->SetStartAndEnd(StartLoc, StartTangent, EndLoc, EndTangent, true); } } // Unregister any owned components that aren't in PreviewRailMeshSegments TArray<USplineMeshComponent*> OwnedSplineMeshComponents; GetComponents(OwnedSplineMeshComponents); for (auto OwnedComponent : OwnedSplineMeshComponents) { if (!PreviewRailMeshSegments.Contains(OwnedComponent)) { OwnedComponent->UnregisterComponent(); } } } // make visualization of the mount follow the contour of the rail if (PreviewMesh_Mount) { float const SplineLen = RailSplineComponent->GetSplineLength(); FQuat const RailRot = RailSplineComponent->GetQuaternionAtDistanceAlongSpline(CurrentPositionOnRail*SplineLen, ESplineCoordinateSpace::World); PreviewMesh_Mount->SetWorldRotation(RailRot); } } }