void UInheritableComponentHandler::ValidateTemplates() { for (int32 Index = 0; Index < Records.Num();) { bool bIsValidAndNecessary = false; { FComponentOverrideRecord& Record = Records[Index]; FComponentKey& ComponentKey = Record.ComponentKey; FName VarName = ComponentKey.GetSCSVariableName(); if (ComponentKey.RefreshVariableName()) { FName NewName = ComponentKey.GetSCSVariableName(); UE_LOG(LogBlueprint, Log, TEXT("ValidateTemplates '%s': variable old name '%s' new name '%s'"), *GetPathNameSafe(this), *VarName.ToString(), *NewName.ToString()); VarName = NewName; MarkPackageDirty(); } if (IsRecordValid(Record)) { if (IsRecordNecessary(Record)) { bIsValidAndNecessary = true; } else { UE_LOG(LogBlueprint, Log, TEXT("ValidateTemplates '%s': overriden template is unnecessary - component '%s' from '%s'"), *GetPathNameSafe(this), *VarName.ToString(), *GetPathNameSafe(ComponentKey.GetComponentOwner())); } } else { UE_LOG(LogBlueprint, Warning, TEXT("ValidateTemplates '%s': overriden template is invalid - component '%s' from '%s'"), *GetPathNameSafe(this), *VarName.ToString(), *GetPathNameSafe(ComponentKey.GetComponentOwner())); } } if (bIsValidAndNecessary) { ++Index; } else { Records.RemoveAtSwap(Index); } } }
UActorComponent* UInheritableComponentHandler::CreateOverridenComponentTemplate(FComponentKey Key) { for (int32 Index = 0; Index < Records.Num(); ++Index) { FComponentOverrideRecord& Record = Records[Index]; if (Record.ComponentKey.Match(Key)) { if (Record.ComponentTemplate) { return Record.ComponentTemplate; } Records.RemoveAtSwap(Index); break; } } auto BestArchetype = FindBestArchetype(Key); if (!BestArchetype) { UE_LOG(LogBlueprint, Warning, TEXT("CreateOverridenComponentTemplate '%s': cannot find archetype for component '%s' from '%s'"), *GetPathNameSafe(this), *Key.GetSCSVariableName().ToString(), *GetPathNameSafe(Key.GetComponentOwner())); return NULL; } ensure(Cast<UBlueprintGeneratedClass>(GetOuter())); auto NewComponentTemplate = NewObject<UActorComponent>( GetOuter(), BestArchetype->GetClass(), BestArchetype->GetFName(), RF_ArchetypeObject | RF_Public | RF_InheritableComponentTemplate, BestArchetype); // HACK: NewObject can return a pre-existing object which will not have been initialized to the archetype. When we remove the old handlers, we mark them pending // kill so we can identify that situation here (see UE-13987/UE-13990) if (NewComponentTemplate->IsPendingKill()) { NewComponentTemplate->ClearFlags(RF_PendingKill); UEngine::FCopyPropertiesForUnrelatedObjectsParams CopyParams; CopyParams.bDoDelta = false; UEngine::CopyPropertiesForUnrelatedObjects(BestArchetype, NewComponentTemplate, CopyParams); } FComponentOverrideRecord NewRecord; NewRecord.ComponentKey = Key; NewRecord.ComponentTemplate = NewComponentTemplate; Records.Add(NewRecord); return NewComponentTemplate; }
FArchive& FArchiveObjectCrc32::operator<<(class UObject*& Object) { FArchive& Ar = *this; if (!Object || !Object->IsIn(RootObject)) { auto UniqueName = GetPathNameSafe(Object); Ar << UniqueName; } else { ObjectsToSerialize.Enqueue(Object); } return Ar; }
FArchive& FArchiveObjectCrc32::operator<<(class UObject*& Object) { FArchive& Ar = *this; // No linker should be a part of the object's state if (Object && Object->IsA<ULinker>()) { Object = NULL; } if (!Object || !Object->IsIn(RootObject)) { auto UniqueName = GetPathNameSafe(Object); Ar << UniqueName; } else { ObjectsToSerialize.Enqueue(Object); } return Ar; }
void FBlueprintNativeCodeGenModule::GenerateSingleAsset(UField* ForConversion, const TCHAR* PlatformName, TSharedPtr<FNativizationSummary> NativizationSummary) { IBlueprintCompilerCppBackendModule& BackEndModule = (IBlueprintCompilerCppBackendModule&)IBlueprintCompilerCppBackendModule::Get(); auto& BackendPCHQuery = BackEndModule.OnPCHFilenameQuery(); const IAssetRegistry& Registry = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry").Get(); FAssetData AssetInfo = Registry.GetAssetByObjectPath(*ForConversion->GetPathName()); FBlueprintNativeCodeGenPaths TargetPaths = GetManifest(PlatformName).GetTargetPaths(); BackendPCHQuery.BindLambda([TargetPaths]()->FString { return TargetPaths.RuntimePCHFilename(); }); FConvertedAssetRecord& ConversionRecord = GetManifest(PlatformName).CreateConversionRecord(*ForConversion->GetPathName(), AssetInfo); TSharedPtr<FString> HeaderSource(new FString()); TSharedPtr<FString> CppSource(new FString()); FBlueprintNativeCodeGenUtils::GenerateCppCode(ForConversion, HeaderSource, CppSource, NativizationSummary); bool bSuccess = !HeaderSource->IsEmpty() || !CppSource->IsEmpty(); // Run the cpp first, because we cue off of the presence of a header for a valid conversion record (see // FConvertedAssetRecord::IsValid) if (!CppSource->IsEmpty()) { if (!FFileHelper::SaveStringToFile(*CppSource, *ConversionRecord.GeneratedCppPath, ForcedEncoding())) { bSuccess &= false; ConversionRecord.GeneratedCppPath.Empty(); } CppSource->Empty(CppSource->Len()); } else { ConversionRecord.GeneratedCppPath.Empty(); } if (bSuccess && !HeaderSource->IsEmpty()) { if (!FFileHelper::SaveStringToFile(*HeaderSource, *ConversionRecord.GeneratedHeaderPath, ForcedEncoding())) { bSuccess &= false; ConversionRecord.GeneratedHeaderPath.Empty(); } HeaderSource->Empty(HeaderSource->Len()); } else { ConversionRecord.GeneratedHeaderPath.Empty(); } if (bSuccess) { GetManifest(PlatformName).GatherModuleDependencies(ForConversion->GetOutermost()); } else { UE_LOG(LogBlueprintCodeGen, Error, TEXT("FBlueprintNativeCodeGenModule::GenerateSingleAsset error: %s"), *GetPathNameSafe(ForConversion)); } BackendPCHQuery.Unbind(); }
bool GetMovementBaseTransform(const UPrimitiveComponent* MovementBase, const FName BoneName, FVector& OutLocation, FQuat& OutQuat) { if (MovementBase) { if (BoneName != NAME_None) { const USkeletalMeshComponent* SkeletalBase = Cast<USkeletalMeshComponent>(MovementBase); if (SkeletalBase) { const int32 BoneIndex = SkeletalBase->GetBoneIndex(BoneName); if (BoneIndex != INDEX_NONE) { const FTransform BoneTransform = SkeletalBase->GetBoneTransform(BoneIndex); OutLocation = BoneTransform.GetLocation(); OutQuat = BoneTransform.GetRotation(); return true; } UE_LOG(LogCharacter, Warning, TEXT("GetMovementBaseTransform(): Invalid bone '%s' for SkeletalMeshComponent base %s"), *BoneName.ToString(), *GetPathNameSafe(MovementBase)); return false; } // TODO: warn if not a skeletal mesh but providing bone index. } // No bone supplied OutLocation = MovementBase->GetComponentLocation(); OutQuat = MovementBase->GetComponentQuat(); return true; } // NULL MovementBase OutLocation = FVector::ZeroVector; OutQuat = FQuat::Identity; return false; }
float UProjectileMovementComponent::GetSimulationTimeStep(float RemainingTime, int32 Iterations) const { if (RemainingTime > MaxSimulationTimeStep) { if (Iterations < MaxSimulationIterations) { // Subdivide moves to be no longer than MaxSimulationTimeStep seconds RemainingTime = FMath::Min(MaxSimulationTimeStep, RemainingTime * 0.5f); } else { // If this is the last iteration, just use all the remaining time. This is usually better than cutting things short, as the simulation won't move far enough otherwise. // Print a throttled warning. #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) static uint32 s_WarningCount = 0; if ((s_WarningCount++ < 100) || (GFrameCounter & 15) == 0) { UE_LOG(LogProjectileMovement, Warning, TEXT("GetSimulationTimeStep() - Max iterations %d hit while remaining time %.6f > MaxSimulationTimeStep (%.3f) for '%s'"), MaxSimulationIterations, RemainingTime, MaxSimulationTimeStep, *GetPathNameSafe(UpdatedComponent)); } #endif } } // no less than MIN_TICK_TIME (to avoid potential divide-by-zero during simulation). return FMath::Max(MIN_TICK_TIME, RemainingTime); }
void FBlueprintCompileReinstancer::ReinstanceFast() { UE_LOG(LogBlueprint, Log, TEXT("BlueprintCompileReinstancer: Doing a fast path refresh on class '%s'."), *GetPathNameSafe(ClassToReinstance)); TArray<UObject*> ObjectsToReplace; GetObjectsOfClass(DuplicatedClass, ObjectsToReplace, /*bIncludeDerivedClasses=*/ false); const bool bIsActor = ClassToReinstance->IsChildOf<AActor>(); const bool bIsAnimInstance = ClassToReinstance->IsChildOf<UAnimInstance>(); const bool bIsComponent = ClassToReinstance->IsChildOf<UActorComponent>(); for (auto Obj : ObjectsToReplace) { UE_LOG(LogBlueprint, Log, TEXT(" Fast path is refreshing (not replacing) %s"), *Obj->GetFullName()); if ((!Obj->IsTemplate() || bIsComponent) && !Obj->IsPendingKill()) { const bool bIsSelected = bIsActor ? Obj->IsSelected() : false; Obj->SetClass(ClassToReinstance); if (bIsActor) { auto Actor = CastChecked<AActor>(Obj); Actor->ReregisterAllComponents(); Actor->RerunConstructionScripts(); if (bIsSelected) { GEditor->SelectActor(Actor, /*bInSelected =*/true, /*bNotify =*/true, false, true); } } if (bIsAnimInstance) { // Initialising the anim instance isn't enough to correctly set up the skeletal mesh again in a // paused world, need to initialise the skeletal mesh component that contains the anim instance. if (USkeletalMeshComponent* SkelComponent = Cast<USkeletalMeshComponent>(Obj->GetOuter())) { SkelComponent->InitAnim(true); } } } } TArray<UObject*> SourceObjects; TMap<UObject*, UObject*> OldToNewInstanceMap; TMap<FStringAssetReference, UObject*> ReinstancedObjectsWeakReferenceMap; FReplaceReferenceHelper::IncludeCDO(DuplicatedClass, ClassToReinstance, OldToNewInstanceMap, SourceObjects, OriginalCDO); FReplaceReferenceHelper::FindAndReplaceReferences(SourceObjects, &ObjectsThatShouldUseOldStuff, ObjectsToReplace, OldToNewInstanceMap, ReinstancedObjectsWeakReferenceMap); }
uint32 FArchiveObjectCrc32::Crc32(UObject* Object, uint32 CRC) { #ifdef DEBUG_ARCHIVE_OBJECT_CRC32 const double StartTime = FPlatformTime::Seconds(); UE_LOG(LogArchiveObjectCrc32, Log, TEXT("### Calculating CRC for object: %s with outer: %s"), *Object->GetName(), Object->GetOuter() ? *Object->GetOuter()->GetName() : TEXT("NULL")); #endif RootObject = Object; if (Object) { TSet<UObject*> SerializedObjects; // Start with the given object ObjectsToSerialize.Enqueue(Object); // Continue until we no longer have any objects to serialized while (ObjectsToSerialize.Dequeue(Object)) { bool bAlreadyProcessed = false; SerializedObjects.Add(Object, &bAlreadyProcessed); // If we haven't already serialized this object if (!bAlreadyProcessed) { #ifdef DEBUG_ARCHIVE_OBJECT_CRC32 UE_LOG(LogArchiveObjectCrc32, Log, TEXT("- Serializing object: %s with outer: %s"), *Object->GetName(), Object->GetOuter() ? *Object->GetOuter()->GetName() : TEXT("NULL")); #endif // Serialize it ObjectBeingSerialized = Object; if (!CustomSerialize(Object)) { Object->Serialize(*this); } ObjectBeingSerialized = NULL; // Calculate the CRC, compounding it with the checksum calculated from the previous object CRC = FCrc::MemCrc32(SerializedObjectData.GetData(), SerializedObjectData.Num(), CRC); #ifdef DEBUG_ARCHIVE_OBJECT_CRC32 UE_LOG(LogArchiveObjectCrc32, Log, TEXT("=> object: '%s', total size: %d bytes, checksum: 0x%08x"), *GetPathNameSafe(Object), SerializedObjectData.Num(), CRC); #endif // Cleanup MemoryWriter.Seek(0L); SerializedObjectData.Empty(); } } // Cleanup SerializedObjects.Empty(); RootObject = NULL; } #ifdef DEBUG_ARCHIVE_OBJECT_CRC32 UE_LOG(LogArchiveObjectCrc32, Log, TEXT("### Finished (%.02f ms), final checksum: 0x%08x"), (FPlatformTime::Seconds() - StartTime) * 1000.0f, CRC); #endif return CRC; }
void UGameplayCueManager::CheckForTooManyRPCs(FName FuncName, const FGameplayCuePendingExecute& PendingCue, const FString& CueID, const FGameplayEffectContext* EffectContext) { if (GameplayCueCheckForTooManyRPCs) { static IConsoleVariable* MaxRPCPerNetUpdateCVar = IConsoleManager::Get().FindConsoleVariable(TEXT("net.MaxRPCPerNetUpdate")); if (MaxRPCPerNetUpdateCVar) { AActor* Owner = PendingCue.OwningComponent ? PendingCue.OwningComponent->GetOwner() : nullptr; UWorld* World = Owner ? Owner->GetWorld() : nullptr; UNetDriver* NetDriver = World ? World->GetNetDriver() : nullptr; if (NetDriver) { const int32 MaxRPCs = MaxRPCPerNetUpdateCVar->GetInt(); for (UNetConnection* ClientConnection : NetDriver->ClientConnections) { if (ClientConnection) { UActorChannel** OwningActorChannelPtr = ClientConnection->ActorChannels.Find(Owner); TSharedRef<FObjectReplicator>* ComponentReplicatorPtr = (OwningActorChannelPtr && *OwningActorChannelPtr) ? (*OwningActorChannelPtr)->ReplicationMap.Find(PendingCue.OwningComponent) : nullptr; if (ComponentReplicatorPtr) { const TArray<FObjectReplicator::FRPCCallInfo>& RemoteFuncInfo = (*ComponentReplicatorPtr)->RemoteFuncInfo; for (const FObjectReplicator::FRPCCallInfo& CallInfo : RemoteFuncInfo) { if (CallInfo.FuncName == FuncName) { if (CallInfo.Calls > MaxRPCs) { const FString Instigator = EffectContext ? EffectContext->ToString() : TEXT("None"); ABILITY_LOG(Warning, TEXT("Attempted to fire %s when no more RPCs are allowed this net update. Max:%d Cue:%s Instigator:%s Component:%s"), *FuncName.ToString(), MaxRPCs, *CueID, *Instigator, *GetPathNameSafe(PendingCue.OwningComponent)); // Returning here to only log once per offending RPC. return; } break; } } } } } } } } }
void UUserDefinedStructEditorData::RecreateDefaultInstance(FString* OutLog) { UStruct* ScriptStruct = GetOwnerStruct(); DefaultStructInstance.Recreate(ScriptStruct); uint8* StructData = DefaultStructInstance.GetStructMemory(); ensure(DefaultStructInstance.IsValid() && DefaultStructInstance.GetStruct() == ScriptStruct); if (DefaultStructInstance.IsValid() && StructData && ScriptStruct) { DefaultStructInstance.SetPackage(ScriptStruct->GetOutermost()); for (TFieldIterator<UProperty> It(ScriptStruct); It; ++It) { UProperty* Property = *It; if (Property) { auto VarDesc = VariablesDescriptions.FindByPredicate(FStructureEditorUtils::FFindByNameHelper<FStructVariableDescription>(Property->GetFName())); if (VarDesc && !VarDesc->CurrentDefaultValue.IsEmpty()) { if (!FBlueprintEditorUtils::PropertyValueFromString(Property, VarDesc->CurrentDefaultValue, StructData)) { const FString Message = FString::Printf(TEXT("Cannot parse value. Property: %s String: \"%s\" ") , (Property ? *Property->GetDisplayNameText().ToString() : TEXT("None")) , *VarDesc->CurrentDefaultValue); UE_LOG(LogClass, Warning, TEXT("UUserDefinedStructEditorData::RecreateDefaultInstance %s Struct: %s "), *Message, *GetPathNameSafe(ScriptStruct)); if (OutLog) { OutLog->Append(Message); } } } } } } }
void AddConvexElemsToRigidActor_AssumesLocked() const { float ContactOffsetFactor, MaxContactOffset; GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset); for (int32 i = 0; i < BodySetup->AggGeom.ConvexElems.Num(); i++) { const FKConvexElem& ConvexElem = BodySetup->AggGeom.ConvexElems[i]; if (ConvexElem.ConvexMesh) { PxTransform PLocalPose; bool bUseNegX = CalcMeshNegScaleCompensation(Scale3D, PLocalPose); PxConvexMeshGeometry PConvexGeom; PConvexGeom.convexMesh = bUseNegX ? ConvexElem.ConvexMeshNegX : ConvexElem.ConvexMesh; PConvexGeom.scale.scale = U2PVector(Scale3DAbs * ConvexElem.GetTransform().GetScale3D().GetAbs()); FTransform ConvexTransform = ConvexElem.GetTransform(); if (ConvexTransform.GetScale3D().X < 0 || ConvexTransform.GetScale3D().Y < 0 || ConvexTransform.GetScale3D().Z < 0) { UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] has negative scale. Not currently supported"), *GetPathNameSafe(BodySetup->GetOuter()), i); } if (ConvexTransform.IsValid()) { PxTransform PElementTransform = U2PTransform(ConvexTransform * RelativeTM); PLocalPose.q *= PElementTransform.q; PLocalPose.p = PElementTransform.p; PLocalPose.p.x *= Scale3D.X; PLocalPose.p.y *= Scale3D.Y; PLocalPose.p.z *= Scale3D.Z; if (PConvexGeom.isValid()) { PxVec3 PBoundsExtents = PConvexGeom.convexMesh->getLocalBounds().getExtents(); ensure(PLocalPose.isValid()); { const float ContactOffset = FMath::Min(MaxContactOffset, ContactOffsetFactor * PBoundsExtents.minElement()); AttachShape_AssumesLocked(PConvexGeom, PLocalPose, ContactOffset); } } else { UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] invalid"), *GetPathNameSafe(BodySetup->GetOuter()), i); } } else { UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] has invalid transform"), *GetPathNameSafe(BodySetup->GetOuter()), i); } } else { UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: ConvexElem is missing ConvexMesh (%d: %s)"), i, *BodySetup->GetPathName()); } } }
void AddBoxesToRigidActor_AssumesLocked() const { float ContactOffsetFactor, MaxContactOffset; GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset); for (int32 i = 0; i < BodySetup->AggGeom.BoxElems.Num(); i++) { const FKBoxElem& BoxElem = BodySetup->AggGeom.BoxElems[i]; PxBoxGeometry PBoxGeom; PBoxGeom.halfExtents.x = (0.5f * BoxElem.X * Scale3DAbs.X); PBoxGeom.halfExtents.y = (0.5f * BoxElem.Y * Scale3DAbs.Y); PBoxGeom.halfExtents.z = (0.5f * BoxElem.Z * Scale3DAbs.Z); FTransform BoxTransform = BoxElem.GetTransform() * RelativeTM; if (PBoxGeom.isValid() && BoxTransform.IsValid()) { PxTransform PLocalPose(U2PTransform(BoxTransform)); PLocalPose.p.x *= Scale3D.X; PLocalPose.p.y *= Scale3D.Y; PLocalPose.p.z *= Scale3D.Z; ensure(PLocalPose.isValid()); { const float ContactOffset = FMath::Min(MaxContactOffset, ContactOffsetFactor * PBoxGeom.halfExtents.minElement()); AttachShape_AssumesLocked(PBoxGeom, PLocalPose, ContactOffset); } } else { UE_LOG(LogPhysics, Warning, TEXT("AddBoxesToRigidActor: [%s] BoxElems[%d] invalid or has invalid transform"), *GetPathNameSafe(BodySetup->GetOuter()), i); } } }
void AddSpheresToRigidActor_AssumesLocked() const { float ContactOffsetFactor, MaxContactOffset; GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset); for (int32 i = 0; i < BodySetup->AggGeom.SphereElems.Num(); i++) { const FKSphereElem& SphereElem = BodySetup->AggGeom.SphereElems[i]; PxSphereGeometry PSphereGeom; PSphereGeom.radius = (SphereElem.Radius * MinScaleAbs); if (ensure(PSphereGeom.isValid())) { FVector LocalOrigin = RelativeTM.TransformPosition(SphereElem.Center); PxTransform PLocalPose(U2PVector(LocalOrigin)); PLocalPose.p *= MinScale; ensure(PLocalPose.isValid()); { const float ContactOffset = FMath::Min(MaxContactOffset, ContactOffsetFactor * PSphereGeom.radius); AttachShape_AssumesLocked(PSphereGeom, PLocalPose, ContactOffset); } } else { UE_LOG(LogPhysics, Warning, TEXT("AddSpheresToRigidActor: [%s] SphereElem[%d] invalid"), *GetPathNameSafe(BodySetup->GetOuter()), i); } } }
void UK2Node_GenericCreateObject::EarlyValidation(class FCompilerResultsLog& MessageLog) const { Super::EarlyValidation(MessageLog); auto ClassPin = GetClassPin(&Pins); const bool bAllowAbstract = ClassPin && ClassPin->LinkedTo.Num(); auto ClassToSpawn = GetClassToSpawn(); if (!UGameplayStatics::CanSpawnObjectOfClass(ClassToSpawn, bAllowAbstract)) { MessageLog.Error(*FString::Printf(*LOCTEXT("GenericCreateObject_WrongClass", "Wrong class to spawn '%s' in @@").ToString(), *GetPathNameSafe(ClassToSpawn)), this); } auto OuterPin = GetOuterPin(); if (!OuterPin || (!OuterPin->DefaultObject && !OuterPin->LinkedTo.Num())) { MessageLog.Error(*LOCTEXT("GenericCreateObject_NoOuter", "Outer object is required in @@").ToString(), this); } }
UObject* FBlueprintNativeCodeGenModule::FindReplacedNameAndOuter(UObject* Object, FName& OutName) const { OutName = NAME_None; UObject* Outer = nullptr; UActorComponent* ActorComponent = Cast<UActorComponent>(Object); if (ActorComponent) { //if is child of a BPGC and not child of a CDO UBlueprintGeneratedClass* BPGC = nullptr; for (UObject* OuterObject = ActorComponent->GetOuter(); OuterObject && !BPGC; OuterObject = OuterObject->GetOuter()) { if (OuterObject->HasAnyFlags(RF_ClassDefaultObject)) { return Outer; } BPGC = Cast<UBlueprintGeneratedClass>(OuterObject); } for (UBlueprintGeneratedClass* SuperBPGC = BPGC; SuperBPGC && (OutName == NAME_None); SuperBPGC = Cast<UBlueprintGeneratedClass>(SuperBPGC->GetSuperClass())) { if (SuperBPGC->InheritableComponentHandler) { FComponentKey FoundKey = SuperBPGC->InheritableComponentHandler->FindKey(ActorComponent); if (FoundKey.IsValid()) { OutName = FoundKey.IsSCSKey() ? FoundKey.GetSCSVariableName() : ActorComponent->GetFName(); Outer = BPGC->GetDefaultObject(false); break; } } if (SuperBPGC->SimpleConstructionScript) { for (auto Node : SuperBPGC->SimpleConstructionScript->GetAllNodes()) { if (Node->ComponentTemplate == ActorComponent) { OutName = Node->VariableName; if (OutName != NAME_None) { Outer = BPGC->GetDefaultObject(false); break; } } } } } } if (Outer && (EReplacementResult::ReplaceCompletely == IsTargetedForReplacement(Object->GetClass()))) { UE_LOG(LogBlueprintCodeGen, Log, TEXT("Object '%s' has replaced name '%s' and outer: '%s'"), *GetPathNameSafe(Object), *OutName.ToString(), *GetPathNameSafe(Outer)); return Outer; } return nullptr; }
EReplacementResult FBlueprintNativeCodeGenModule::IsTargetedForReplacement(const UObject* Object) const { if (Object == nullptr) { return EReplacementResult::DontReplace; } const UStruct* Struct = Cast<UStruct>(Object); const UEnum* Enum = Cast<UEnum>(Object); if (Struct == nullptr && Enum == nullptr) { return EReplacementResult::DontReplace; } EReplacementResult Result = EReplacementResult::ReplaceCompletely; if (const UClass* BlueprintClass = Cast<UClass>(Struct)) { if (UBlueprint* Blueprint = Cast<UBlueprint>(BlueprintClass->ClassGeneratedBy)) { static const FBoolConfigValueHelper NativizeAnimBPOnlyWhenNonReducibleFuncitons(TEXT("BlueprintNativizationSettings"), TEXT("bNativizeAnimBPOnlyWhenNonReducibleFuncitons")); if (NativizeAnimBPOnlyWhenNonReducibleFuncitons) { if (UAnimBlueprint* AnimBlueprint = Cast<UAnimBlueprint>(Blueprint)) { ensure(AnimBlueprint->bHasBeenRegenerated); if (AnimBlueprint->bHasAnyNonReducibleFunction == UBlueprint::EIsBPNonReducible::No) { UE_LOG(LogBlueprintCodeGen, Log, TEXT("AnimBP %s without non-reducible functions is excluded from nativization"), *GetPathNameSafe(Blueprint)); Result = EReplacementResult::GenerateStub; } } } const EBlueprintType UnconvertableBlueprintTypes[] = { //BPTYPE_Const, // WTF is a "const" Blueprint? BPTYPE_MacroLibrary, BPTYPE_LevelScript, }; EBlueprintType BlueprintType = Blueprint->BlueprintType; for (int32 TypeIndex = 0; TypeIndex < ARRAY_COUNT(UnconvertableBlueprintTypes); ++TypeIndex) { if (BlueprintType == UnconvertableBlueprintTypes[TypeIndex]) { Result = EReplacementResult::GenerateStub; } } static const FBoolConfigValueHelper DontNativizeDataOnlyBP(TEXT("BlueprintNativizationSettings"), TEXT("bDontNativizeDataOnlyBP")); if (DontNativizeDataOnlyBP) { if (FBlueprintEditorUtils::IsDataOnlyBlueprint(Blueprint)) { return EReplacementResult::DontReplace; } } for (UBlueprintGeneratedClass* ParentClassIt = Cast<UBlueprintGeneratedClass>(BlueprintClass->GetSuperClass()) ; ParentClassIt; ParentClassIt = Cast<UBlueprintGeneratedClass>(ParentClassIt->GetSuperClass())) { EReplacementResult ParentResult = IsTargetedForReplacement(ParentClassIt); if (ParentResult != EReplacementResult::ReplaceCompletely) { Result = EReplacementResult::GenerateStub; } } for (TAssetSubclassOf<UBlueprint> ExcludedBlueprintTypeAsset : ExcludedBlueprintTypes) { UClass* ExcludedBPClass = ExcludedBlueprintTypeAsset.Get(); if (!ExcludedBPClass) { ExcludedBPClass = ExcludedBlueprintTypeAsset.LoadSynchronous(); } if (ExcludedBPClass && Blueprint->IsA(ExcludedBPClass)) { Result = EReplacementResult::GenerateStub; } } } } auto IsObjectFromDeveloperPackage = [](const UObject* Obj) -> bool { return Obj && Obj->GetOutermost()->HasAllPackagesFlags(PKG_Developer); }; auto IsDeveloperObject = [&](const UObject* Obj) -> bool { if (Obj) { if (IsObjectFromDeveloperPackage(Obj)) { return true; } const UStruct* StructToTest = Obj->IsA<UStruct>() ? CastChecked<const UStruct>(Obj) : Obj->GetClass(); for (; StructToTest; StructToTest = StructToTest->GetSuperStruct()) { if (IsObjectFromDeveloperPackage(StructToTest)) { return true; } } } return false; }; if (Object && (IsEditorOnlyObject(Object) || IsDeveloperObject(Object))) { UE_LOG(LogBlueprintCodeGen, Warning, TEXT("Object %s depends on Editor or Development stuff. It shouldn't be cooked."), *GetPathNameSafe(Object)); return EReplacementResult::DontReplace; } // check blacklists: // we can't use FindObject, because we may be converting a type while saving if (Enum && ExcludedAssetTypes.Find(Enum->GetPathName()) != INDEX_NONE) { Result = EReplacementResult::GenerateStub; } while (Struct) { if (ExcludedAssetTypes.Find(Struct->GetPathName()) != INDEX_NONE) { Result = EReplacementResult::GenerateStub; } Struct = Struct->GetSuperStruct(); } if (ExcludedAssets.Contains(Object->GetOutermost())) { Result = EReplacementResult::GenerateStub; } return Result; }
void UBodySetup::AddSpheresToRigidActor(PxRigidActor* PDestActor, const FTransform& RelativeTM, float MinScale, float MinScaleAbs, TArray<PxShape*>* NewShapes) const { float ContactOffsetFactor, MaxContactOffset; GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset); PxMaterial* PDefaultMat = GetDefaultPhysMaterial(); for (int32 i = 0; i < AggGeom.SphereElems.Num(); i++) { const FKSphereElem& SphereElem = AggGeom.SphereElems[i]; PxSphereGeometry PSphereGeom; PSphereGeom.radius = (SphereElem.Radius * MinScaleAbs); if (ensure(PSphereGeom.isValid())) { FVector LocalOrigin = RelativeTM.TransformPosition(SphereElem.Center); PxTransform PLocalPose(U2PVector(LocalOrigin)); PLocalPose.p *= MinScale; ensure(PLocalPose.isValid()); PxShape* NewShape = PDestActor->createShape(PSphereGeom, *PDefaultMat, PLocalPose); if (NewShapes) { NewShapes->Add(NewShape); } const float ContactOffset = FMath::Min(MaxContactOffset, ContactOffsetFactor * PSphereGeom.radius); NewShape->setContactOffset(ContactOffset); } else { UE_LOG(LogPhysics, Warning, TEXT("AddSpheresToRigidActor: [%s] SphereElem[%d] invalid"), *GetPathNameSafe(GetOuter()), i); } } }
void UBodySetup::AddBoxesToRigidActor(PxRigidActor* PDestActor, const FTransform& RelativeTM, const FVector& Scale3D, const FVector& Scale3DAbs, TArray<PxShape*>* NewShapes) const { float ContactOffsetFactor, MaxContactOffset; GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset); PxMaterial* PDefaultMat = GetDefaultPhysMaterial(); for (int32 i = 0; i < AggGeom.BoxElems.Num(); i++) { const FKBoxElem& BoxElem = AggGeom.BoxElems[i]; PxBoxGeometry PBoxGeom; PBoxGeom.halfExtents.x = (0.5f * BoxElem.X * Scale3DAbs.X); PBoxGeom.halfExtents.y = (0.5f * BoxElem.Y * Scale3DAbs.Y); PBoxGeom.halfExtents.z = (0.5f * BoxElem.Z * Scale3DAbs.Z); FTransform BoxTransform = BoxElem.GetTransform() * RelativeTM; if (PBoxGeom.isValid() && BoxTransform.IsValid()) { PxTransform PLocalPose(U2PTransform(BoxTransform)); PLocalPose.p.x *= Scale3D.X; PLocalPose.p.y *= Scale3D.Y; PLocalPose.p.z *= Scale3D.Z; ensure(PLocalPose.isValid()); PxShape* NewShape = PDestActor->createShape(PBoxGeom, *PDefaultMat, PLocalPose); if (NewShapes) { NewShapes->Add(NewShape); } const float ContactOffset = FMath::Min(MaxContactOffset, ContactOffsetFactor * PBoxGeom.halfExtents.minElement()); NewShape->setContactOffset(ContactOffset); } else { UE_LOG(LogPhysics, Warning, TEXT("AddBoxesToRigidActor: [%s] BoxElems[%d] invalid or has invalid transform"), *GetPathNameSafe(GetOuter()), i); } } }
void UBodySetup::AddSphylsToRigidActor(PxRigidActor* PDestActor, const FTransform& RelativeTM, const FVector& Scale3D, const FVector& Scale3DAbs, TArray<PxShape*>* NewShapes) const { float ContactOffsetFactor, MaxContactOffset; GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset); PxMaterial* PDefaultMat = GetDefaultPhysMaterial(); float ScaleRadius = FMath::Max(Scale3DAbs.X, Scale3DAbs.Y); float ScaleLength = Scale3DAbs.Z; for (int32 i = 0; i < AggGeom.SphylElems.Num(); i++) { const FKSphylElem& SphylElem = AggGeom.SphylElems[i]; // this is a bit confusing since radius and height is scaled // first apply the scale first float Radius = FMath::Max(SphylElem.Radius * ScaleRadius, 0.1f); float Length = SphylElem.Length + SphylElem.Radius * 2.f; float HalfLength = Length * ScaleLength * 0.5f; Radius = FMath::Clamp(Radius, 0.1f, HalfLength); //radius is capped by half length float HalfHeight = HalfLength - Radius; HalfHeight = FMath::Max(0.1f, HalfHeight); PxCapsuleGeometry PCapsuleGeom; PCapsuleGeom.halfHeight = HalfHeight; PCapsuleGeom.radius = Radius; if (PCapsuleGeom.isValid()) { // The stored sphyl transform assumes the sphyl axis is down Z. In PhysX, it points down X, so we twiddle the matrix a bit here (swap X and Z and negate Y). PxTransform PLocalPose(U2PVector(RelativeTM.TransformPosition(SphylElem.Center)), U2PQuat(SphylElem.Orientation) * U2PSphylBasis); PLocalPose.p.x *= Scale3D.X; PLocalPose.p.y *= Scale3D.Y; PLocalPose.p.z *= Scale3D.Z; ensure(PLocalPose.isValid()); PxShape* NewShape = PDestActor->createShape(PCapsuleGeom, *PDefaultMat, PLocalPose); if (NewShapes) { NewShapes->Add(NewShape); } const float ContactOffset = FMath::Min(MaxContactOffset, ContactOffsetFactor * PCapsuleGeom.radius); NewShape->setContactOffset(ContactOffset); } else { UE_LOG(LogPhysics, Warning, TEXT("AddSphylsToRigidActor: [%s] SphylElems[%d] invalid"), *GetPathNameSafe(GetOuter()), i); } } }
bool FUniqueNetIdRepl::ImportTextItem(const TCHAR*& Buffer, int32 PortFlags, UObject* Parent, FOutputDevice* ErrorText) { SetUniqueNetId(nullptr); bool bShouldWarn = true; if (Buffer) { static FString InvalidString(TEXT("INVALID")); if (Buffer[0] == TEXT('\0') || Buffer == InvalidString) { // An empty string or the word invalid are just considered expected invalid FUniqueNetIdRepls. No need to warn about those. bShouldWarn = false; } else { checkf(UOnlineEngineInterface::Get() && UOnlineEngineInterface::Get()->IsLoaded(), TEXT("Attempted to ImportText to FUniqueNetIdRepl while OSS is not loaded. Parent:%s"), *GetPathNameSafe(Parent)); FString Contents(Buffer); UniqueIdFromString(Contents); } } if (bShouldWarn && !IsValid()) { #if !NO_LOGGING ErrorText->CategorizedLogf(LogNet.GetCategoryName(), ELogVerbosity::Warning, TEXT("Failed to import text to FUniqueNetIdRepl Parent:%s"), *GetPathNameSafe(Parent)); #endif } return true; }
void UBodySetup::AddConvexElemsToRigidActor(PxRigidActor* PDestActor, const FTransform& RelativeTM, const FVector& Scale3D, const FVector& Scale3DAbs, TArray<PxShape*>* NewShapes) const { float ContactOffsetFactor, MaxContactOffset; GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset); PxMaterial* PDefaultMat = GetDefaultPhysMaterial(); for (int32 i = 0; i < AggGeom.ConvexElems.Num(); i++) { const FKConvexElem& ConvexElem = AggGeom.ConvexElems[i]; if (ConvexElem.ConvexMesh) { PxTransform PLocalPose; bool bUseNegX = CalcMeshNegScaleCompensation(Scale3D, PLocalPose); PxConvexMeshGeometry PConvexGeom; PConvexGeom.convexMesh = bUseNegX ? ConvexElem.ConvexMeshNegX : ConvexElem.ConvexMesh; PConvexGeom.scale.scale = U2PVector(Scale3DAbs * ConvexElem.GetTransform().GetScale3D().GetAbs()); FTransform ConvexTransform = ConvexElem.GetTransform(); if (ConvexTransform.GetScale3D().X < 0 || ConvexTransform.GetScale3D().Y < 0 || ConvexTransform.GetScale3D().Z < 0) { UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] has negative scale. Not currently supported"), *GetPathNameSafe(GetOuter()), i); } if (ConvexTransform.IsValid()) { PxTransform PElementTransform = U2PTransform(ConvexTransform * RelativeTM); PLocalPose.q *= PElementTransform.q; PLocalPose.p = PElementTransform.p; PLocalPose.p.x *= Scale3D.X; PLocalPose.p.y *= Scale3D.Y; PLocalPose.p.z *= Scale3D.Z; if (PConvexGeom.isValid()) { PxVec3 PBoundsExtents = PConvexGeom.convexMesh->getLocalBounds().getExtents(); ensure(PLocalPose.isValid()); PxShape* NewShape = PDestActor->createShape(PConvexGeom, *PDefaultMat, PLocalPose); if (NewShapes) { NewShapes->Add(NewShape); } const float ContactOffset = FMath::Min(MaxContactOffset, ContactOffsetFactor * PBoundsExtents.minElement()); NewShape->setContactOffset(ContactOffset); } else { UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] invalid"), *GetPathNameSafe(GetOuter()), i); } } else { UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] has invalid transform"), *GetPathNameSafe(GetOuter()), i); } } else { UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: ConvexElem is missing ConvexMesh (%d: %s)"), i, *GetPathName()); } } }
void FBlueprintCompileReinstancer::ReinstanceInner(bool bForceAlwaysReinstance) { if (ClassToReinstance && DuplicatedClass) { static const FBoolConfigValueHelper ReinstanceOnlyWhenNecessary(TEXT("Kismet"), TEXT("bReinstanceOnlyWhenNecessary"), GEngineIni); bool bShouldReinstance = true; // See if we need to do a full reinstance or can do the faster refresh path (when enabled or no values were modified, and the structures match) if (ReinstanceOnlyWhenNecessary && !bForceAlwaysReinstance) { BP_SCOPED_COMPILER_EVENT_STAT(EKismetReinstancerStats_ReplaceClassNoReinsancing); const UBlueprintGeneratedClass* BPClassA = Cast<const UBlueprintGeneratedClass>(DuplicatedClass); const UBlueprintGeneratedClass* BPClassB = Cast<const UBlueprintGeneratedClass>(ClassToReinstance); const UBlueprint* BP = Cast<const UBlueprint>(ClassToReinstance->ClassGeneratedBy); static const FBoolConfigValueHelper ChangeDefaultValueWithoutReinstancing(TEXT("Kismet"), TEXT("bChangeDefaultValueWithoutReinstancing"), GEngineIni); const bool bTheSameDefaultValues = (BP != nullptr) && (ClassToReinstanceDefaultValuesCRC != 0) && (BP->CrcPreviousCompiledCDO == ClassToReinstanceDefaultValuesCRC); const bool bTheSameLayout = (BPClassA != nullptr) && (BPClassB != nullptr) && FStructUtils::TheSameLayout(BPClassA, BPClassB, true); const bool bAllowedToDoFastPath = (ChangeDefaultValueWithoutReinstancing || bTheSameDefaultValues) && bTheSameLayout; if (bAllowedToDoFastPath) { ReinstanceFast(); bShouldReinstance = false; } } if (bShouldReinstance) { UE_LOG(LogBlueprint, Log, TEXT("BlueprintCompileReinstancer: Doing a full reinstance on class '%s'"), *GetPathNameSafe(ClassToReinstance)); ReplaceInstancesOfClass(DuplicatedClass, ClassToReinstance, OriginalCDO, &ObjectsThatShouldUseOldStuff); } else if (ClassToReinstance->IsChildOf<UActorComponent>()) { // ReplaceInstancesOfClass() handles this itself, if we had to re-instance ReconstructOwnerInstances(ClassToReinstance); } } }
void UTimelineTemplate::PostDuplicate(bool bDuplicateForPIE) { Super::PostDuplicate(bDuplicateForPIE); UObject* NewCurveOuter = GetOuter(); #if WITH_EDITOR // The outer should always be a BlueprintGeneratedClass, however the Curves get put into the Blueprint, however if they belong to the Transient package, that's where the duplicated Blueprint should be. if(GetOutermost() != GetTransientPackage()) { if(UBlueprintGeneratedClass* BPClass = Cast<UBlueprintGeneratedClass>(GetOuter())) { NewCurveOuter = BPClass->ClassGeneratedBy; } } #endif // WITH_EDITOR for(TArray<struct FTTFloatTrack>::TIterator It = FloatTracks.CreateIterator();It;++It) { FTTFloatTrack& Track = *It; if( Track.CurveFloat != NULL ) { // Do not duplicate external curves unless duplicating to a transient package if(!Track.CurveFloat->GetOuter()->IsA(UPackage::StaticClass()) || GetOutermost() == GetTransientPackage()) { Track.CurveFloat = DuplicateObject<UCurveFloat>(Track.CurveFloat, NewCurveOuter, *MakeUniqueCurveName(Track.CurveFloat, NewCurveOuter)); } } else { UE_LOG(LogBlueprint, Warning, TEXT("Timeline %s Track %s in %s has an invalid curve. Please fix!"), *TimelineTemplateNameToVariableName(GetFName()), *Track.TrackName.ToString(), *GetPathNameSafe(GetOuter())); } } for(TArray<struct FTTEventTrack>::TIterator It = EventTracks.CreateIterator();It;++It) { FTTEventTrack& Track = *It; if( Track.CurveKeys != NULL ) { // Do not duplicate external curves unless duplicating to a transient package if(!Track.CurveKeys->GetOuter()->IsA(UPackage::StaticClass()) || GetOutermost() == GetTransientPackage()) { Track.CurveKeys = DuplicateObject<UCurveFloat>(Track.CurveKeys, NewCurveOuter, *MakeUniqueCurveName(Track.CurveKeys, NewCurveOuter)); } } else { UE_LOG(LogBlueprint, Warning, TEXT("Timeline %s Track %s in %s has an invalid curve. Please fix!"), *TimelineTemplateNameToVariableName(GetFName()), *Track.TrackName.ToString(), *GetPathNameSafe(GetOuter())); } } for(TArray<struct FTTVectorTrack>::TIterator It = VectorTracks.CreateIterator();It;++It) { FTTVectorTrack& Track = *It; if( Track.CurveVector != NULL ) { // Do not duplicate external curves unless duplicating to a transient package if(!Track.CurveVector->GetOuter()->IsA(UPackage::StaticClass()) || GetOutermost() == GetTransientPackage()) { Track.CurveVector = DuplicateObject<UCurveVector>(Track.CurveVector, NewCurveOuter, *MakeUniqueCurveName(Track.CurveVector, NewCurveOuter)); } } else { UE_LOG(LogBlueprint, Warning, TEXT("Timeline %s Track %s in %s has an invalid curve. Please fix!"), *TimelineTemplateNameToVariableName(GetFName()), *Track.TrackName.ToString(), *GetPathNameSafe(GetOuter())); } } for(TArray<struct FTTLinearColorTrack>::TIterator It = LinearColorTracks.CreateIterator();It;++It) { FTTLinearColorTrack& Track = *It; if( Track.CurveLinearColor != NULL ) { // Do not duplicate external curves unless duplicating to a transient package if(!Track.CurveLinearColor->GetOuter()->IsA(UPackage::StaticClass()) || GetOutermost() == GetTransientPackage()) { Track.CurveLinearColor = DuplicateObject<UCurveLinearColor>(Track.CurveLinearColor, NewCurveOuter, *MakeUniqueCurveName(Track.CurveLinearColor, NewCurveOuter)); } } else { UE_LOG(LogBlueprint, Warning, TEXT("Timeline %s Track %s in %s has an invalid curve. Please fix!"), *TimelineTemplateNameToVariableName(GetFName()), *Track.TrackName.ToString(), *GetPathNameSafe(GetOuter())); } } TimelineGuid = FGuid::NewGuid(); }