void FComponentSpacePoseLink::EvaluateComponentSpace(FComponentSpacePoseContext& Output) { #if DO_CHECK checkf( !bProcessed, TEXT( "EvaluateComponentSpace already in progress, circular link for AnimInstance [%s] Blueprint [%s]" ), \ *Output.AnimInstanceProxy->GetAnimInstanceName(), *GetFullNameSafe(IAnimClassInterface::GetActualAnimClass(Output.AnimInstanceProxy->GetAnimClassInterface()))); TGuardValue<bool> CircularGuard(bProcessed, true); #endif #if ENABLE_ANIMGRAPH_TRAVERSAL_DEBUG checkf(InitializationCounter.IsSynchronizedWith(Output.AnimInstanceProxy->GetInitializationCounter()), TEXT("Calling EvaluateComponentSpace without initialization!")); checkf(CachedBonesCounter.IsSynchronizedWith(Output.AnimInstanceProxy->GetCachedBonesCounter()), TEXT("Calling EvaluateComponentSpace without CachedBones!")); checkf(UpdateCounter.IsSynchronizedWith(Output.AnimInstanceProxy->GetUpdateCounter()), TEXT("Calling EvaluateComponentSpace without Update for this node!")); EvaluationCounter.SynchronizeWith(Output.AnimInstanceProxy->GetEvaluationCounter()); #endif if (LinkedNode != NULL) { LinkedNode->EvaluateComponentSpace(Output); #if WITH_EDITOR Output.AnimInstanceProxy->RegisterWatchedPose(Output.Pose, LinkID); #endif } else { //@TODO: Warning here? Output.ResetToRefPose(); } // Detect non valid output #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) if (Output.ContainsNaN()) { // Show bone transform with some useful debug info for (const FTransform& Bone : Output.Pose.GetPose().GetBones()) { if (Bone.ContainsNaN()) { ensureMsgf(!Bone.ContainsNaN(), TEXT("Bone transform contains NaN from AnimInstance:[%s] Node:[%s] Value:[%s]") , *Output.AnimInstanceProxy->GetAnimInstanceName(), LinkedNode ? *LinkedNode->StaticStruct()->GetName() : TEXT("NULL"), *Bone.ToString()); } } } if (!Output.IsNormalized()) { // Show bone transform with some useful debug info for (const FTransform& Bone : Output.Pose.GetPose().GetBones()) { if (!Bone.IsRotationNormalized()) { ensureMsgf(Bone.IsRotationNormalized(), TEXT("Bone Rotation not normalized from AnimInstance:[%s] Node:[%s] Value:[%s]") , *Output.AnimInstanceProxy->GetAnimInstanceName(), LinkedNode ? *LinkedNode->StaticStruct()->GetName() : TEXT("NULL"), *Bone.ToString()); } } } #endif }
void FPoseLinkBase::CacheBones(const FAnimationCacheBonesContext& Context) { #if DO_CHECK checkf( !bProcessed, TEXT( "CacheBones already in progress, circular link for AnimInstance [%s] Blueprint [%s]" ), \ *Context.AnimInstanceProxy->GetAnimInstanceName(), *GetFullNameSafe(IAnimClassInterface::GetActualAnimClass(Context.AnimInstanceProxy->GetAnimClassInterface()))); TGuardValue<bool> CircularGuard(bProcessed, true); #endif #if ENABLE_ANIMGRAPH_TRAVERSAL_DEBUG CachedBonesCounter.SynchronizeWith(Context.AnimInstanceProxy->GetCachedBonesCounter()); #endif if (LinkedNode != NULL) { LinkedNode->CacheBones(Context); } }
void FPoseLinkBase::Update(const FAnimationUpdateContext& Context) { QUICK_SCOPE_CYCLE_COUNTER(STAT_FPoseLinkBase_Update); #if DO_CHECK checkf( !bProcessed, TEXT( "Update already in progress, circular link for AnimInstance [%s] Blueprint [%s]" ), \ *Context.AnimInstanceProxy->GetAnimInstanceName(), *GetFullNameSafe(IAnimClassInterface::GetActualAnimClass(Context.AnimInstanceProxy->GetAnimClassInterface()))); TGuardValue<bool> CircularGuard(bProcessed, true); #endif #if WITH_EDITOR if (GIsEditor) { if (LinkedNode == NULL) { //@TODO: Should only do this when playing back AttemptRelink(Context); } // Record the node line activation if (LinkedNode != NULL) { if (Context.AnimInstanceProxy->IsBeingDebugged()) { Context.AnimInstanceProxy->RecordNodeVisit(LinkID, SourceLinkID, Context.GetFinalBlendWeight()); } } } #endif #if ENABLE_ANIMGRAPH_TRAVERSAL_DEBUG checkf(InitializationCounter.IsSynchronizedWith(Context.AnimInstanceProxy->GetInitializationCounter()), TEXT("Calling Update without initialization!")); UpdateCounter.SynchronizeWith(Context.AnimInstanceProxy->GetUpdateCounter()); #endif if (LinkedNode != NULL) { LinkedNode->Update(Context); } }
void FPoseLinkBase::Initialize(const FAnimationInitializeContext& Context) { #if DO_CHECK checkf(!bProcessed, TEXT("Initialize already in progress, circular link for AnimInstance [%s] Blueprint [%s]"), \ *Context.AnimInstanceProxy->GetAnimInstanceName(), *GetFullNameSafe(IAnimClassInterface::GetActualAnimClass(Context.AnimInstanceProxy->GetAnimClassInterface()))); TGuardValue<bool> CircularGuard(bProcessed, true); #endif AttemptRelink(Context); #if ENABLE_ANIMGRAPH_TRAVERSAL_DEBUG InitializationCounter.SynchronizeWith(Context.AnimInstanceProxy->GetInitializationCounter()); // Initialization will require update to be called before an evaluate. UpdateCounter.Reset(); #endif // Do standard initialization if (LinkedNode != NULL) { LinkedNode->Initialize(Context); } }
/** Change the Pawn's base. */ void ACharacter::SetBase( UPrimitiveComponent* NewBaseComponent, const FName InBoneName, bool bNotifyPawn ) { // If NewBaseComponent is null, ignore bone name. const FName BoneName = (NewBaseComponent ? InBoneName : NAME_None); // See what changed. const bool bBaseChanged = (NewBaseComponent != BasedMovement.MovementBase); const bool bBoneChanged = (BoneName != BasedMovement.BoneName); if (bBaseChanged || bBoneChanged) { // Verify no recursion. APawn* Loop = (NewBaseComponent ? Cast<APawn>(NewBaseComponent->GetOwner()) : NULL); for( ; Loop!=NULL; Loop=Cast<APawn>(Loop->GetMovementBase()) ) { if( Loop == this ) { UE_LOG(LogCharacter, Warning, TEXT(" SetBase failed! Recursion detected. Pawn %s already based on %s."), *GetName(), *NewBaseComponent->GetName()); return; } } // Set base. UPrimitiveComponent* OldBase = BasedMovement.MovementBase; BasedMovement.MovementBase = NewBaseComponent; BasedMovement.BoneName = BoneName; if (CharacterMovement) { if (bBaseChanged) { MovementBaseUtility::RemoveTickDependency(CharacterMovement->PrimaryComponentTick, OldBase); MovementBaseUtility::AddTickDependency(CharacterMovement->PrimaryComponentTick, NewBaseComponent); } if (NewBaseComponent) { // Update OldBaseLocation/Rotation as those were referring to a different base // ... but not when handling replication for proxies (since they are going to copy this data from the replicated values anyway) if (!bInBaseReplication) { CharacterMovement->SaveBaseLocation(); } // Enable pre-cloth tick if we are standing on a physics object, as we need to to use post-physics transforms CharacterMovement->PreClothComponentTick.SetTickFunctionEnable(NewBaseComponent->IsSimulatingPhysics()); } else { BasedMovement.BoneName = NAME_None; // None, regardless of whether user tried to set a bone name, since we have no base component. BasedMovement.bRelativeRotation = false; CharacterMovement->CurrentFloor.Clear(); CharacterMovement->PreClothComponentTick.SetTickFunctionEnable(false); } if (Role == ROLE_Authority || Role == ROLE_AutonomousProxy) { BasedMovement.bServerHasBaseComponent = (BasedMovement.MovementBase != NULL); // Also set on proxies for nicer debugging. UE_LOG(LogCharacter, Verbose, TEXT("Setting base on %s for '%s' to '%s'"), Role == ROLE_Authority ? TEXT("Server") : TEXT("AutoProxy"), *GetName(), *GetFullNameSafe(NewBaseComponent)); } else { UE_LOG(LogCharacter, Verbose, TEXT("Setting base on Client for '%s' to '%s'"), *GetName(), *GetFullNameSafe(NewBaseComponent)); } } // Notify this actor of his new floor. if ( bNotifyPawn ) { BaseChange(); } } }
/** Change the Pawn's base. */ void ACharacter::SetBase( UPrimitiveComponent* NewBaseComponent, bool bNotifyPawn ) { if (NewBaseComponent != MovementBase) { // Verify no recursion. APawn* Loop = (NewBaseComponent ? Cast<APawn>(NewBaseComponent->GetOwner()) : NULL); for( ; Loop!=NULL; Loop=Cast<APawn>(Loop->GetMovementBase()) ) { if( Loop == this ) { UE_LOG(LogCharacter, Warning, TEXT(" SetBase failed! Recursion detected. Pawn %s already based on %s."), *GetName(), *NewBaseComponent->GetName()); return; } } // Set base. MovementBase = NewBaseComponent; if (Role == ROLE_Authority) { // Update replicated value UE_LOG(LogCharacter, Verbose, TEXT("Setting base on server for '%s' to '%s'"), *GetName(), *GetFullNameSafe(NewBaseComponent)); RelativeMovement.MovementBase = NewBaseComponent; RelativeMovement.bServerHasBaseComponent = (NewBaseComponent != NULL); // Flag whether the server had a non-null base. } else { UE_LOG(LogCharacter, Verbose, TEXT("Setting base on CLIENT for '%s' to '%s'"), *GetName(), *GetFullNameSafe(NewBaseComponent)); } // Update relative location/rotation if ( Role == ROLE_Authority || Role == ROLE_AutonomousProxy ) { if (MovementBaseUtility::UseRelativePosition(MovementBase)) { RelativeMovement.Location = GetActorLocation() - MovementBase->GetComponentLocation(); RelativeMovement.Rotation = (FRotationMatrix(GetActorRotation()) * FRotationMatrix(MovementBase->GetComponentRotation()).GetTransposed()).Rotator(); } } // Notify this actor of his new floor. if ( bNotifyPawn ) { BaseChange(); } if (MovementBase && CharacterMovement) { // Update OldBaseLocation/Rotation as those were referring to a different base CharacterMovement->OldBaseLocation = MovementBase->GetComponentLocation(); CharacterMovement->OldBaseRotation = MovementBase->GetComponentRotation(); } } }
UObject* UObjectPropertyBase::FindImportedObject( const UProperty* Property, UObject* OwnerObject, UClass* ObjectClass, UClass* RequiredMetaClass, const TCHAR* Text, uint32 PortFlags/*=0*/ ) { UObject* Result = NULL; check( ObjectClass->IsChildOf(RequiredMetaClass) ); bool AttemptNonQualifiedSearch = (PortFlags & PPF_AttemptNonQualifiedSearch) != 0; // if we are importing default properties, first look for a matching subobject by // looking through the archetype chain at each outer and stop once the outer chain reaches the owning class's default object if (PortFlags & PPF_ParsingDefaultProperties) { for (UObject* SearchStart = OwnerObject; Result == NULL && SearchStart != NULL; SearchStart = SearchStart->GetOuter()) { UObject* ScopedSearchRoot = SearchStart; while (Result == NULL && ScopedSearchRoot != NULL) { Result = StaticFindObject(ObjectClass, ScopedSearchRoot, Text); // don't think it's possible to get a non-subobject here, but it doesn't hurt to check if (Result != NULL && !Result->IsTemplate(RF_ClassDefaultObject)) { Result = NULL; } ScopedSearchRoot = ScopedSearchRoot->GetArchetype(); } if (SearchStart->HasAnyFlags(RF_ClassDefaultObject)) { break; } } } // if we have a parent, look in the parent, then it's outer, then it's outer, ... // this is because exported object properties that point to objects in the level aren't // fully qualified, and this will step up the nested object chain to solve any name // collisions within a nested object tree UObject* ScopedSearchRoot = OwnerObject; while (Result == NULL && ScopedSearchRoot != NULL) { Result = StaticFindObject(ObjectClass, ScopedSearchRoot, Text); // disallow class default subobjects here while importing defaults // this prevents the use of a subobject name that doesn't exist in the scope of the default object being imported // from grabbing some other subobject with the same name and class in some other arbitrary default object if (Result != NULL && (PortFlags & PPF_ParsingDefaultProperties) && Result->IsTemplate(RF_ClassDefaultObject)) { Result = NULL; } ScopedSearchRoot = ScopedSearchRoot->GetOuter(); } if (Result == NULL) { // attempt to find a fully qualified object Result = StaticFindObject(ObjectClass, NULL, Text); if (Result == NULL) { // match any object of the correct class whose path contains the specified path Result = StaticFindObject(ObjectClass, ANY_PACKAGE, Text); // disallow class default subobjects here while importing defaults if (Result != NULL && (PortFlags & PPF_ParsingDefaultProperties) && Result->IsTemplate(RF_ClassDefaultObject)) { Result = NULL; } } } // if we haven;t found it yet, then try to find it without a qualified name if (!Result) { const TCHAR* Dot = FCString::Strrchr(Text, '.'); if (Dot && AttemptNonQualifiedSearch) { // search with just the object name Result = FindImportedObject(Property, OwnerObject, ObjectClass, RequiredMetaClass, Dot + 1); } FString NewText(Text); // if it didn't have a dot, then maybe they just gave a uasset package name if (!Dot && !Result) { int32 LastSlash = NewText.Find(TEXT("/"), ESearchCase::CaseSensitive, ESearchDir::FromEnd); if (LastSlash >= 0) { NewText += TEXT("."); NewText += (Text + LastSlash + 1); Dot = FCString::Strrchr(*NewText, '.'); } } // If we still can't find it, try to load it. (Only try to load fully qualified names) if(!Result && Dot) { #if USE_CIRCULAR_DEPENDENCY_LOAD_DEFERRING FLinkerLoad* Linker = (OwnerObject != nullptr) ? OwnerObject->GetClass()->GetLinker() : nullptr; const bool bDeferAssetImports = (Linker != nullptr) && (Linker->LoadFlags & LOAD_DeferDependencyLoads); if (bDeferAssetImports) { Result = Linker->RequestPlaceholderValue(ObjectClass, Text); } if (Result == nullptr) #endif // USE_CIRCULAR_DEPENDENCY_LOAD_DEFERRING { uint32 LoadFlags = LOAD_NoWarn | LOAD_FindIfFail; UE_LOG(LogProperty, Verbose, TEXT("FindImportedObject is attempting to import [%s] (class = %s) with StaticLoadObject"), Text, *GetFullNameSafe(ObjectClass)); Result = StaticLoadObject(ObjectClass, NULL, Text, NULL, LoadFlags, NULL); #if USE_DEFERRED_DEPENDENCY_CHECK_VERIFICATION_TESTS check(!bDeferAssetImports || !Result || !FBlueprintSupport::IsInBlueprintPackage(Result)); #endif // USE_DEFERRED_DEPENDENCY_CHECK_VERIFICATION_TESTS } } } // if we found an object, and we have a parent, make sure we are in the same package if the found object is private, unless it's a cross level property if (Result && !Result->HasAnyFlags(RF_Public) && OwnerObject && Result->GetOutermost() != OwnerObject->GetOutermost()) { const UObjectPropertyBase* ObjectProperty = dynamic_cast<const UObjectPropertyBase*>(Property); if ( !ObjectProperty || !ObjectProperty->AllowCrossLevel()) { UE_LOG(LogProperty, Warning, TEXT("Illegal TEXT reference to a private object in external package (%s) from referencer (%s). Import failed..."), *Result->GetFullName(), *OwnerObject->GetFullName()); Result = NULL; } } check(!Result || Result->IsA(RequiredMetaClass)); return Result; }
void FDuplicateDataReader::SerializeFail() { extern UObject* GSerializedObject; UE_LOG(LogObj, Fatal, TEXT("FDuplicateDataReader Overread. SerializedObject = %s SerializedProperty = %s"), *GetFullNameSafe(GSerializedObject), *GetFullNameSafe(GetSerializedProperty())); }