Пример #1
0
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;
}
Пример #2
0
/**
 * 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;
}