USceneComponent* FComponentReference::GetComponent(AActor* OwningActor) const { USceneComponent* Result = NULL; // Component is specified directly, use that if(OverrideComponent.IsValid()) { Result = OverrideComponent.Get(); } else { // Look in Actor if specified, OwningActor if not AActor* SearchActor = (OtherActor != NULL) ? OtherActor : OwningActor; if(SearchActor) { if(ComponentProperty != NAME_None) { UObjectPropertyBase* ObjProp = FindField<UObjectPropertyBase>(SearchActor->GetClass(), ComponentProperty); if(ObjProp != NULL) { // .. and return the component that is there Result = Cast<USceneComponent>(ObjProp->GetObjectPropertyValue_InContainer(SearchActor)); } } else { Result = Cast<USceneComponent>(SearchActor->GetRootComponent()); } } } return Result; }
/** * Exports the property values for the specified object as text to the output device. * * @param Context Context from which the set of 'inner' objects is extracted. If NULL, an object iterator will be used. * @param Out the output device to send the exported text to * @param ObjectClass the class of the object to dump properties for * @param Object the address of the object to dump properties for * @param Indent number of spaces to prepend to each line of output * @param DiffClass the class to use for comparing property values when delta export is desired. * @param Diff the address of the object to use for determining whether a property value should be exported. If the value in Object matches the corresponding * value in Diff, it is not exported. Specify NULL to export all properties. * @param Parent the UObject corresponding to Object * @param PortFlags flags used for modifying the output and/or behavior of the export */ void ExportProperties ( const FExportObjectInnerContext* Context, FOutputDevice& Out, UClass* ObjectClass, uint8* Object, int32 Indent, UClass* DiffClass, uint8* Diff, UObject* Parent, uint32 PortFlags, UObject* ExportRootScope ) { FString ThisName = TEXT("(none)"); check(ObjectClass != NULL); for( UProperty* Property = ObjectClass->PropertyLink; Property; Property = Property->PropertyLinkNext ) { if (!Property->ShouldPort(PortFlags)) continue; ThisName = Property->GetName(); UArrayProperty* ArrayProperty = Cast<UArrayProperty>(Property); UObjectPropertyBase* ExportObjectProp = (Property->PropertyFlags & CPF_ExportObject) != 0 ? Cast<UObjectPropertyBase>(Property) : NULL; const uint32 ExportFlags = PortFlags | PPF_Delimited; if ( ArrayProperty != NULL ) { // Export dynamic array. UProperty* InnerProp = ArrayProperty->Inner; ExportObjectProp = (Property->PropertyFlags & CPF_ExportObject) != 0 ? Cast<UObjectPropertyBase>(InnerProp) : NULL; // This is used as the default value in the case of an array property that has // fewer elements than the exported object. uint8* StructDefaults = NULL; UStructProperty* StructProperty = Cast<UStructProperty>(InnerProp); if ( StructProperty != NULL ) { checkSlow(StructProperty->Struct); StructDefaults = (uint8*)FMemory::Malloc(StructProperty->Struct->GetStructureSize()); StructProperty->InitializeValue(StructDefaults); } for( int32 PropertyArrayIndex=0; PropertyArrayIndex<Property->ArrayDim; PropertyArrayIndex++ ) { void* Arr = Property->ContainerPtrToValuePtr<void>(Object, PropertyArrayIndex); FScriptArrayHelper ArrayHelper(ArrayProperty, Arr); void* DiffArr = NULL; if( DiffClass ) { DiffArr = Property->ContainerPtrToValuePtrForDefaults<void>(DiffClass, Diff, PropertyArrayIndex); } // we won't use this if DiffArr is NULL, but we have to set it up to something FScriptArrayHelper DiffArrayHelper(ArrayProperty, DiffArr); bool bAnyElementDiffered = false; for( int32 DynamicArrayIndex=0; DynamicArrayIndex<ArrayHelper.Num(); DynamicArrayIndex++ ) { FString Value; // compare each element's value manually so that elements which match the NULL value for the array's inner property type // but aren't in the diff array are still exported uint8* SourceData = ArrayHelper.GetRawPtr(DynamicArrayIndex); uint8* DiffData = DiffArr && DynamicArrayIndex < DiffArrayHelper.Num() ? DiffArrayHelper.GetRawPtr(DynamicArrayIndex) : StructDefaults; bool bExportItem = DiffData == NULL || (DiffData != SourceData && !InnerProp->Identical(SourceData, DiffData, ExportFlags)); if ( bExportItem ) { bAnyElementDiffered = true; InnerProp->ExportTextItem(Value, SourceData, DiffData, Parent, ExportFlags, ExportRootScope); if(ExportObjectProp) { UObject* Obj = ExportObjectProp->GetObjectPropertyValue(ArrayHelper.GetRawPtr(DynamicArrayIndex)); check(!Obj || Obj->IsValidLowLevel()); if( Obj && !Obj->HasAnyMarks(OBJECTMARK_TagImp) ) { // only export the BEGIN OBJECT block for a component if Parent is the component's Outer....when importing subobject definitions, // (i.e. BEGIN OBJECT), whichever BEGIN OBJECT block a component's BEGIN OBJECT block is located within is the object that will be // used as the Outer to create the component // Is this an array of components? if ( InnerProp->HasAnyPropertyFlags(CPF_InstancedReference) ) { if ( Obj->GetOuter() == Parent ) { // Don't export more than once. Obj->Mark(OBJECTMARK_TagImp); UExporter::ExportToOutputDevice( Context, Obj, NULL, Out, TEXT("T3D"), Indent, PortFlags ); } else { // set the OBJECTMARK_TagExp flag so that the calling code knows we wanted to export this object Obj->Mark(OBJECTMARK_TagExp); } } else { // Don't export more than once. Obj->Mark(OBJECTMARK_TagImp); UExporter::ExportToOutputDevice( Context, Obj, NULL, Out, TEXT("T3D"), Indent, PortFlags ); } } } Out.Logf( TEXT("%s%s(%i)=%s\r\n"), FCString::Spc(Indent), *Property->GetName(), DynamicArrayIndex, *Value ); } // if some other element has already been determined to differ from the defaults, then export this item with no data so that // the different array's size is maintained on import (this item will get the default values for that index, if any) // however, if no elements of the array have changed, we still don't want to export anything // so that the array size will also be taken from the defaults, which won't be the case if any element is exported else if (bAnyElementDiffered) { Out.Logf( TEXT("%s%s(%i)=()\r\n"), FCString::Spc(Indent), *Property->GetName(), DynamicArrayIndex ); } } } if (StructDefaults) { StructProperty->DestroyValue(StructDefaults); FMemory::Free(StructDefaults); } } else { for( int32 PropertyArrayIndex=0; PropertyArrayIndex<Property->ArrayDim; PropertyArrayIndex++ ) { FString Value; // Export single element. uint8* DiffData = (DiffClass && Property->IsInContainer(DiffClass->GetPropertiesSize())) ? Diff : NULL; if( Property->ExportText_InContainer( PropertyArrayIndex, Value, Object, DiffData, Parent, ExportFlags, ExportRootScope ) ) { if ( ExportObjectProp ) { UObject* Obj = ExportObjectProp->GetObjectPropertyValue(Property->ContainerPtrToValuePtr<void>(Object, PropertyArrayIndex)); if( Obj && !Obj->HasAnyMarks(OBJECTMARK_TagImp) ) { // only export the BEGIN OBJECT block for a component if Parent is the component's Outer....when importing subobject definitions, // (i.e. BEGIN OBJECT), whichever BEGIN OBJECT block a component's BEGIN OBJECT block is located within is the object that will be // used as the Outer to create the component if ( Property->HasAnyPropertyFlags(CPF_InstancedReference) ) { if ( Obj->GetOuter() == Parent ) { // Don't export more than once. Obj->Mark(OBJECTMARK_TagImp); UExporter::ExportToOutputDevice( Context, Obj, NULL, Out, TEXT("T3D"), Indent, PortFlags ); } else { // set the OBJECTMARK_TagExp flag so that the calling code knows we wanted to export this object Obj->Mark(OBJECTMARK_TagExp); } } else { // Don't export more than once. Obj->Mark(OBJECTMARK_TagImp); UExporter::ExportToOutputDevice( Context, Obj, NULL, Out, TEXT("T3D"), Indent, PortFlags ); } } } if( Property->ArrayDim == 1 ) { Out.Logf( TEXT("%s%s=%s\r\n"), FCString::Spc(Indent), *Property->GetName(), *Value ); } else { Out.Logf( TEXT("%s%s(%i)=%s\r\n"), FCString::Spc(Indent), *Property->GetName(), PropertyArrayIndex, *Value ); } } } } } // Allows to import/export C++ properties in case the automatic unreal script mesh wouldn't work. Parent->ExportCustomProperties(Out, Indent); }
void UWidgetBlueprintGeneratedClass::InitializeWidget(UUserWidget* UserWidget) const { #if WITH_EDITORONLY_DATA UWidgetTree* ClonedTree = DuplicateObject<UWidgetTree>(DesignerWidgetTree ? DesignerWidgetTree : WidgetTree, UserWidget); #else UWidgetTree* ClonedTree = DuplicateObject<UWidgetTree>(WidgetTree, UserWidget); #endif #if WITH_EDITOR UserWidget->WidgetGeneratedBy = ClassGeneratedBy; #endif if ( ClonedTree ) { ClonedTree->SetFlags(RF_Transactional); UserWidget->WidgetTree = ClonedTree; UClass* WidgetBlueprintClass = UserWidget->GetClass(); for(UWidgetAnimation* Animation : Animations) { UWidgetAnimation* Anim = DuplicateObject<UWidgetAnimation>( Animation, UserWidget ); if( Anim->MovieScene ) { // Find property with the same name as the template and assign the new widget to it. UObjectPropertyBase* Prop = FindField<UObjectPropertyBase>(WidgetBlueprintClass, Anim->MovieScene->GetFName()); if(Prop) { Prop->SetObjectPropertyValue_InContainer(UserWidget, Anim); } } } ClonedTree->ForEachWidget([&] (UWidget* Widget) { // Not fatal if NULL, but shouldn't happen if ( !ensure(Widget != nullptr) ) { return; } #if WITH_EDITOR Widget->WidgetGeneratedBy = ClassGeneratedBy; #endif // TODO UMG Make this an FName FString VariableName = Widget->GetName(); Widget->bCreatedByConstructionScript = true; // Indicate it comes from a blueprint so it gets cleared when we rerun construction scripts // Find property with the same name as the template and assign the new widget to it. UObjectPropertyBase* Prop = FindField<UObjectPropertyBase>(WidgetBlueprintClass, *VariableName); if ( Prop ) { Prop->SetObjectPropertyValue_InContainer(UserWidget, Widget); UObject* Value = Prop->GetObjectPropertyValue_InContainer(UserWidget); check(Value == Widget); } // Perform binding for ( const FDelegateRuntimeBinding& Binding : Bindings ) { //TODO UMG Make this faster. if ( Binding.ObjectName == VariableName ) { UDelegateProperty* DelegateProperty = FindField<UDelegateProperty>(Widget->GetClass(), FName(*( Binding.PropertyName.ToString() + TEXT("Delegate") ))); if ( !DelegateProperty ) { DelegateProperty = FindField<UDelegateProperty>(Widget->GetClass(), Binding.PropertyName); } if ( DelegateProperty ) { bool bSourcePathBound = false; if ( Binding.SourcePath.IsValid() ) { bSourcePathBound = Widget->AddBinding(DelegateProperty, UserWidget, Binding.SourcePath); } // If no native binder is found then the only possibility is that the binding is for // a delegate that doesn't match the known native binders available and so we // fallback to just attempting to bind to the function directly. if ( bSourcePathBound == false ) { FScriptDelegate* ScriptDelegate = DelegateProperty->GetPropertyValuePtr_InContainer(Widget); if ( ScriptDelegate ) { ScriptDelegate->BindUFunction(UserWidget, Binding.FunctionName); } } } } } // Initialize Navigation Data if (Widget->Navigation) { Widget->Navigation->ResolveExplictRules(ClonedTree); } #if WITH_EDITOR Widget->ConnectEditorData(); #endif }); // Bind any delegates on widgets BindDynamicDelegates(UserWidget); //TODO UMG Add OnWidgetInitialized? } }
void USimpleConstructionScript::ExecuteScriptOnActor(AActor* Actor, const FTransform& RootTransform, bool bIsDefaultTransform) { if(RootNodes.Num() > 0) { TSet<UActorComponent*> AllComponentsCreatedBySCS; TInlineComponentArray<UActorComponent*> InstancedComponents; for(auto NodeIt = RootNodes.CreateIterator(); NodeIt; ++NodeIt) { USCS_Node* RootNode = *NodeIt; if(RootNode != nullptr) { // Get all native scene components TInlineComponentArray<USceneComponent*> Components; Actor->GetComponents(Components); for (int32 Index = Components.Num()-1; Index >= 0; --Index) { USceneComponent* SceneComponent = Components[Index]; if (SceneComponent->CreationMethod == EComponentCreationMethod::Instance) { Components.RemoveAt(Index); } else { // Handle the native sub-component of an instance component case USceneComponent* ParentSceneComponent = SceneComponent->GetTypedOuter<USceneComponent>(); if (ParentSceneComponent && ParentSceneComponent->CreationMethod == EComponentCreationMethod::Instance) { Components.RemoveAt(Index); } } } // Get the native root component; if it's not set, the first native scene component will be used as root. This matches what's done in the SCS editor. USceneComponent* RootComponent = Actor->GetRootComponent(); if(RootComponent == nullptr && Components.Num() > 0) { RootComponent = Components[0]; } // If the root node specifies that it has a parent USceneComponent* ParentComponent = nullptr; if(RootNode->ParentComponentOrVariableName != NAME_None) { // Get the Actor class object UClass* ActorClass = Actor->GetClass(); check(ActorClass != nullptr); // If the root node is parented to a "native" component (i.e. in the 'Components' array) if(RootNode->bIsParentComponentNative) { for(int32 CompIndex = 0; CompIndex < Components.Num(); ++CompIndex) { // If we found a match, remember the index if(Components[CompIndex]->GetFName() == RootNode->ParentComponentOrVariableName) { ParentComponent = Components[CompIndex]; break; } } } else { // In the non-native case, the SCS node's variable name property is used as the parent identifier UObjectPropertyBase* Property = FindField<UObjectPropertyBase>(ActorClass, RootNode->ParentComponentOrVariableName); if(Property != nullptr) { // If we found a matching property, grab its value and use that as the parent for this node ParentComponent = Cast<USceneComponent>(Property->GetObjectPropertyValue_InContainer(Actor)); } } } // Create the new component instance and any child components it may have UActorComponent* InstancedComponent = RootNode->ExecuteNodeOnActor(Actor, ParentComponent != nullptr ? ParentComponent : RootComponent, &RootTransform, bIsDefaultTransform); if(InstancedComponent != nullptr) { InstancedComponents.Add(InstancedComponent); } // get list of every component SCS created, in case some of them aren't in the attachment hierarchy any more (e.g. rigid bodies) TInlineComponentArray<USceneComponent*> ComponentsAfterSCS; Actor->GetComponents(ComponentsAfterSCS); for (USceneComponent* C : ComponentsAfterSCS) { if (Components.Contains(C) == false) { AllComponentsCreatedBySCS.Add(C); } } } } // Register all instanced SCS components once SCS execution has finished; sorted in order to register the scene component hierarchy first, followed by the remaining actor components (in case they happen to depend on something in the scene hierarchy) InstancedComponents.Sort([](const UActorComponent& A, const UActorComponent& B) { return A.IsA<USceneComponent>(); }); for(auto InstancedComponent : InstancedComponents) { RegisterInstancedComponent(InstancedComponent); } // now that the instanced components in the attachment hierarchy are registered, register any other components that SCS made but aren't in the attachment hierarchy for whatever reason. for (auto C : AllComponentsCreatedBySCS) { if (C->IsRegistered() == false) { C->RegisterComponent(); } } } else if(Actor->GetRootComponent() == NULL) // Must have a root component at the end of SCS, so if we don't have one already (from base class), create a SceneComponent now { USceneComponent* SceneComp = NewObject<USceneComponent>(Actor); SceneComp->SetFlags(RF_Transactional); SceneComp->CreationMethod = EComponentCreationMethod::SimpleConstructionScript; SceneComp->SetWorldTransform(RootTransform); Actor->SetRootComponent(SceneComp); SceneComp->RegisterComponent(); } }
UPrimitiveComponent* UPhysicsConstraintComponent::GetComponentInternal(EConstraintFrame::Type Frame) const { UPrimitiveComponent* PrimComp = NULL; FName ComponentName = NAME_None; AActor* Actor = NULL; // Frame 1 if(Frame == EConstraintFrame::Frame1) { // Use override component if specified if(OverrideComponent1.IsValid()) { return OverrideComponent1.Get(); } ComponentName = ComponentName1.ComponentName; Actor = ConstraintActor1; } // Frame 2 else { // Use override component if specified if(OverrideComponent2.IsValid()) { return OverrideComponent2.Get(); } ComponentName = ComponentName2.ComponentName; Actor = ConstraintActor2; } // If neither actor nor component name specified, joint to 'world' if(Actor != NULL || ComponentName != NAME_None) { // If no actor specified, but component name is - use Owner if(Actor == NULL) { Actor = GetOwner(); } // If we now have an Actor, lets find a component if(Actor != NULL) { // No name specified, use the root component if(ComponentName == NAME_None) { PrimComp = Cast<UPrimitiveComponent>(Actor->GetRootComponent()); } // Name specified, see if we can find that property.. else { UObjectPropertyBase* ObjProp = FindField<UObjectPropertyBase>(Actor->GetClass(), ComponentName); if(ObjProp != NULL) { // .. and return the component that is there PrimComp = Cast<UPrimitiveComponent>(ObjProp->GetObjectPropertyValue_InContainer(Actor)); } } } } return PrimComp; }