FComponentVisualizer::FPropertyNameAndIndex FComponentVisualizer::GetComponentPropertyName(const UActorComponent* Component) { if (Component) { const AActor* CompOwner = Component->GetOwner(); if (CompOwner) { // Iterate over UObject* fields of this actor UClass* ActorClass = CompOwner->GetClass(); for (TFieldIterator<UObjectProperty> It(ActorClass); It; ++It) { // See if this property points to the component in question UObjectProperty* ObjectProp = *It; for (int32 Index = 0; Index < ObjectProp->ArrayDim; ++Index) { UObject* Object = ObjectProp->GetObjectPropertyValue(ObjectProp->ContainerPtrToValuePtr<void>(CompOwner, Index)); if (Object == Component) { // It does! Return this name return FPropertyNameAndIndex(ObjectProp->GetFName(), Index); } } } // If nothing found, look in TArray<UObject*> fields for (TFieldIterator<UArrayProperty> It(ActorClass); It; ++It) { UArrayProperty* ArrayProp = *It; if (UObjectProperty* InnerProp = Cast<UObjectProperty>(It->Inner)) { FScriptArrayHelper ArrayHelper(ArrayProp, ArrayProp->ContainerPtrToValuePtr<void>(CompOwner)); for (int32 Index = 0; Index < ArrayHelper.Num(); ++Index) { UObject* Object = InnerProp->GetObjectPropertyValue(ArrayHelper.GetRawPtr(Index)); if (Object == Component) { return FPropertyNameAndIndex(ArrayProp->GetFName(), Index); } } } } } } // Didn't find actor property referencing this component return FPropertyNameAndIndex(); }
FName FComponentEditorUtils::FindVariableNameGivenComponentInstance(UActorComponent* ComponentInstance) { check(ComponentInstance != nullptr); // First see if the name just works if (AActor* OwnerActor = ComponentInstance->GetOwner()) { UClass* OwnerActorClass = OwnerActor->GetClass(); if (UObjectProperty* TestProperty = FindField<UObjectProperty>(OwnerActorClass, ComponentInstance->GetFName())) { if (ComponentInstance->GetClass()->IsChildOf(TestProperty->PropertyClass)) { return TestProperty->GetFName(); } } } // Name mismatch, try finding a differently named variable pointing to the the component (the mismatch should only be possible for native components) if (UActorComponent* Archetype = Cast<UActorComponent>(ComponentInstance->GetArchetype())) { if (AActor* OwnerActor = Archetype->GetOwner()) { UClass* OwnerClass = OwnerActor->GetClass(); AActor* OwnerCDO = CastChecked<AActor>(OwnerClass->GetDefaultObject()); check(OwnerCDO->HasAnyFlags(RF_ClassDefaultObject)); for (TFieldIterator<UObjectProperty> PropIt(OwnerClass, EFieldIteratorFlags::IncludeSuper); PropIt; ++PropIt) { UObjectProperty* TestProperty = *PropIt; if (Archetype->GetClass()->IsChildOf(TestProperty->PropertyClass)) { void* TestPropertyInstanceAddress = TestProperty->ContainerPtrToValuePtr<void>(OwnerCDO); UObject* ObjectPointedToByProperty = TestProperty->GetObjectPropertyValue(TestPropertyInstanceAddress); if (ObjectPointedToByProperty == Archetype) { // This property points to the component archetype, so it's an anchor even if it was named wrong return TestProperty->GetFName(); } } } } } return NAME_None; }