void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val) { mScene= static_cast<KX_Scene *>(val); if (mBlenderShader) mBlenderShader->SetScene(mScene); OnConstruction(); }
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 KX_BlenderMaterial::Replace_IScene(SCA_IScene *val) { mScene= static_cast<KX_Scene *>(val); OnConstruction(); }
void AActor::RerunConstructionScripts() { // 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) { // 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 FComponentInstanceDataCache InstanceDataCache(this); // If there are attached objects detach them and store the socket names TArray<AActor*> AttachedActors; GetAttachedActors(AttachedActors); // Struct to store info about attached actors struct FAttachedActorInfo { AActor* AttachedActor; FName AttachedToSocket; }; // Save info about attached actors TArray<FAttachedActorInfo> AttachedActorInfos; 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->bCreatedByConstructionScript ) { // Save info about actor to reattach FAttachedActorInfo Info; Info.AttachedActor = AttachedActor; Info.AttachedToSocket = EachRoot->AttachSocketName; AttachedActorInfos.Add(Info); // Now detach it AttachedActor->Modify(); EachRoot->DetachFromParent(true); } } // Save off original pose of the actor FTransform OldTransform = FTransform::Identity; FName SocketName; AActor* Parent = NULL; if (RootComponent != NULL) { // Do not need to detach if root component is not going away if(RootComponent->AttachParent != NULL && RootComponent->bCreatedByConstructionScript) { 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; } SocketName = RootComponent->AttachSocketName; //detach it to remove any scaling RootComponent->DetachFromParent(true); } OldTransform = RootComponent->ComponentToWorld; } // Destroy existing components DestroyConstructedComponents(); // Reset random streams ResetPropertiesForConstruction(); // Run the construction scripts OnConstruction(OldTransform); if(Parent) { USceneComponent* ChildRoot = GetRootComponent(); USceneComponent* ParentRoot = Parent->GetRootComponent(); if(ChildRoot != NULL && ParentRoot != NULL) { ChildRoot->AttachTo( ParentRoot, SocketName, EAttachLocation::KeepWorldPosition ); } } // Apply per-instance data. InstanceDataCache.ApplyToActor(this); // 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->GetAttachParentActor() == NULL) { USceneComponent* ChildRoot = Info.AttachedActor->GetRootComponent(); if (ChildRoot && ChildRoot->AttachParent != RootComponent) { ChildRoot->AttachTo(RootComponent, Info.AttachedToSocket, EAttachLocation::KeepWorldPosition); ChildRoot->UpdateComponentToWorld(); } } } // Restore the undo buffer GUndo = CurrentTransaction; } }