Ejemplo n.º 1
2
UActorComponent* AActor::AddComponent(FName TemplateName, bool bManualAttachment, const FTransform& RelativeTransform, const UObject* ComponentTemplateContext)
{
	UActorComponent* Template = nullptr;
	UBlueprintGeneratedClass* BlueprintGeneratedClass = Cast<UBlueprintGeneratedClass>((ComponentTemplateContext != nullptr) ? ComponentTemplateContext->GetClass() : GetClass());
	while(BlueprintGeneratedClass != nullptr)
	{
		Template = BlueprintGeneratedClass->FindComponentTemplateByName(TemplateName);
		if(nullptr != Template)
		{
			break;
		}
		BlueprintGeneratedClass = Cast<UBlueprintGeneratedClass>(BlueprintGeneratedClass->GetSuperClass());
	}

	bool bIsSceneComponent = false;
	UActorComponent* NewActorComp = CreateComponentFromTemplate(Template);
	if(NewActorComp != nullptr)
	{
		// Call function to notify component it has been created
		NewActorComp->OnComponentCreated();
		
		// The user has the option of doing attachment manually where they have complete control or via the automatic rule
		// that the first component added becomes the root component, with subsequent components attached to the root.
		USceneComponent* NewSceneComp = Cast<USceneComponent>(NewActorComp);
		if(NewSceneComp != nullptr)
		{
			if (!bManualAttachment)
			{
				if (RootComponent == nullptr)
				{
					RootComponent = NewSceneComp;
				}
				else
				{
					NewSceneComp->AttachTo(RootComponent);
				}
			}

			NewSceneComp->SetRelativeTransform(RelativeTransform);

			bIsSceneComponent = true;
		}

		// Register component, which will create physics/rendering state, now component is in correct position
		NewActorComp->RegisterComponent();

		UWorld* World = GetWorld();
		if (!bRunningUserConstructionScript && World && bIsSceneComponent)
		{
			UPrimitiveComponent* NewPrimitiveComponent = Cast<UPrimitiveComponent>(NewActorComp);
			if (NewPrimitiveComponent && ACullDistanceVolume::CanBeAffectedByVolumes(NewPrimitiveComponent))
			{
				World->UpdateCullDistanceVolumes(this, NewPrimitiveComponent);
			}
		}
	}

	return NewActorComp;
}
Ejemplo n.º 2
0
UActorComponent* UActorBlueprintLibrary::AttachComponentOfClass(UObject* WorldContextObject, TSubclassOf<UActorComponent> ComponentClass, AActor* Owner, FName ComponentName, USceneComponent* AttachTo, FName SocketName)
{
	if (!Owner)
	{
		return nullptr;
	}

	UActorComponent* Component = NewObject<UActorComponent>(Owner, *ComponentClass, ComponentName);
	if (!Component)
	{
		return nullptr;
	}

	Component->RegisterComponent();
	Component->OnComponentCreated();

	USceneComponent* SceneComponent = Cast<USceneComponent>(Component);
	if (SceneComponent)
	{
		SceneComponent->SetWorldLocation(Owner->GetActorLocation());
		SceneComponent->SetWorldRotation(Owner->GetActorRotation());

		USceneComponent* AttachToComponent = AttachTo ? AttachTo : Owner->GetRootComponent();

		SceneComponent->AttachToComponent(AttachToComponent, FAttachmentTransformRules::KeepWorldTransform, SocketName);
	}

	return Component;
}
UActorComponent* FComponentEditorUtils::DuplicateComponent(UActorComponent* TemplateComponent)
{
	check(TemplateComponent);

	UActorComponent* NewCloneComponent = nullptr;
	AActor* Actor = TemplateComponent->GetOwner();
	if (!TemplateComponent->IsEditorOnly() && Actor)
	{
		Actor->Modify();
		UClass* ComponentClass = TemplateComponent->GetClass();
		FName NewComponentName = *FComponentEditorUtils::GenerateValidVariableName(ComponentClass, Actor);

		bool bKeepWorldLocationOnAttach = false;

		const bool bTemplateTransactional = TemplateComponent->HasAllFlags(RF_Transactional);
		TemplateComponent->SetFlags(RF_Transactional);

		NewCloneComponent = DuplicateObject<UActorComponent>(TemplateComponent, Actor, NewComponentName );
		
		if (!bTemplateTransactional)
		{
			TemplateComponent->ClearFlags(RF_Transactional);
		}
			
		USceneComponent* NewSceneComponent = Cast<USceneComponent>(NewCloneComponent);
		if (NewSceneComponent)
		{
			// Ensure the clone doesn't think it has children
			NewSceneComponent->AttachChildren.Empty();

			// If the clone is a scene component without an attach parent, attach it to the root (can happen when duplicating the root component)
			if (!NewSceneComponent->GetAttachParent())
			{
				USceneComponent* RootComponent = Actor->GetRootComponent();
				check(RootComponent);

				// ComponentToWorld is not a UPROPERTY, so make sure the clone has calculated it properly before attachment
				NewSceneComponent->UpdateComponentToWorld();

				NewSceneComponent->AttachTo(RootComponent, NAME_None, EAttachLocation::KeepWorldPosition);
			}
		}

		NewCloneComponent->OnComponentCreated();

		// Add to SerializedComponents array so it gets saved
		Actor->AddInstanceComponent(NewCloneComponent);
		
		// Register the new component
		NewCloneComponent->RegisterComponent();

		// Rerun construction scripts
		Actor->RerunConstructionScripts();
	}

	return NewCloneComponent;
}
Ejemplo n.º 4
0
PyObject *py_ue_register_component(ue_PyUObject *self, PyObject * args) {

	ue_py_check(self);

	if (!self->ue_object->IsA<UActorComponent>()) {
		return PyErr_Format(PyExc_Exception, "uobject is not a component");
	}

	UActorComponent *component = (UActorComponent *)self->ue_object;

	component->RegisterComponent();

	Py_INCREF(Py_None);
	return Py_None;
}
Ejemplo n.º 5
0
PyObject *py_ue_add_actor_component(ue_PyUObject * self, PyObject * args) {

	ue_py_check(self);

	PyObject *obj;
	char *name;
	if (!PyArg_ParseTuple(args, "Os:add_actor_component", &obj, &name)) {
		return NULL;
	}

	if (!self->ue_object->IsA<AActor>()) {
		return PyErr_Format(PyExc_Exception, "uobject is not an AActor");
	}

	AActor *actor = (AActor *)self->ue_object;

	if (!ue_is_pyuobject(obj)) {
		return PyErr_Format(PyExc_Exception, "argument is not a UObject");
	}

	ue_PyUObject *py_obj = (ue_PyUObject *)obj;

	if (!py_obj->ue_object->IsA<UClass>()) {
		return PyErr_Format(PyExc_Exception, "argument is not a class");
	}

	UActorComponent *component = NewObject<UActorComponent>(actor, (UClass *)py_obj->ue_object, FName(UTF8_TO_TCHAR(name)));
	if (!component)
		return PyErr_Format(PyExc_Exception, "unable to create component");

	if (actor->GetWorld()) {
		component->RegisterComponent();
	}

	PyObject *ret = (PyObject *)ue_get_python_wrapper(component);
	if (!ret)
		return PyErr_Format(PyExc_Exception, "uobject is in invalid state");
	Py_INCREF(ret);
	return ret;

}
void FComponentEditorUtils::PasteComponents(TArray<UActorComponent*>& OutPastedComponents, AActor* TargetActor, USceneComponent* TargetComponent)
{
	check(TargetActor);

	// Get the text from the clipboard
	FString TextToImport;
	FPlatformMisc::ClipboardPaste(TextToImport);

	// Get a new component object factory for the clipboard content
	TSharedRef<FComponentObjectTextFactory> Factory = FComponentObjectTextFactory::Get(TextToImport);

	TargetActor->Modify();

	USceneComponent* TargetParent = TargetComponent ? TargetComponent->GetAttachParent() : nullptr;
	for (auto& NewObjectPair : Factory->NewObjectMap)
	{
		// Get the component object instance
		UActorComponent* NewActorComponent = NewObjectPair.Value;
		check(NewActorComponent);

		// Relocate the instance from the transient package to the Actor and assign it a unique object name
		FString NewComponentName = FComponentEditorUtils::GenerateValidVariableName(NewActorComponent->GetClass(), TargetActor);
		NewActorComponent->Rename(*NewComponentName, TargetActor, REN_DontCreateRedirectors | REN_DoNotDirty);

		if (auto NewSceneComponent = Cast<USceneComponent>(NewActorComponent))
		{
			// Default to attaching to the target component's parent if possible, otherwise attach to the root
			USceneComponent* NewComponentParent = TargetParent ? TargetParent : TargetActor->GetRootComponent();
			
			// Check to see if there's an entry for the current component in the set of parent components
			if (Factory->ParentMap.Contains(NewObjectPair.Key))
			{
				// Get the parent component name
				FName ParentName = Factory->ParentMap[NewObjectPair.Key];
				if (Factory->NewObjectMap.Contains(ParentName))
				{
					// The parent should by definition be a scene component
					NewComponentParent = CastChecked<USceneComponent>(Factory->NewObjectMap[ParentName]);
				}
			}

			//@todo: Fix pasting when the pasted component was a root
			//NewSceneComponent->UpdateComponentToWorld();
			if (NewComponentParent)
			{
				// Reattach the current node to the parent node
				NewSceneComponent->AttachTo(NewComponentParent, NAME_None/*, EAttachLocation::KeepWorldPosition*/);
			}
			else
			{
				// There is no root component and this component isn't the child of another component in the map, so make it the root
				TargetActor->SetRootComponent(NewSceneComponent);
			}
		}

		TargetActor->AddInstanceComponent(NewActorComponent);
		NewActorComponent->RegisterComponent();

		OutPastedComponents.Add(NewActorComponent);
	}

	// Rerun construction scripts
	TargetActor->RerunConstructionScripts();
}
Ejemplo n.º 7
0
PyObject *py_ue_add_actor_component(ue_PyUObject * self, PyObject * args)
{

	ue_py_check(self);

	PyObject *obj;
	char *name;
	PyObject *py_parent = nullptr;
	if (!PyArg_ParseTuple(args, "Os|O:add_actor_component", &obj, &name, &py_parent))
	{
		return NULL;
	}

	if (!self->ue_object->IsA<AActor>())
	{
		return PyErr_Format(PyExc_Exception, "uobject is not an AActor");
	}

	AActor *actor = (AActor *)self->ue_object;

	if (!ue_is_pyuobject(obj))
	{
		return PyErr_Format(PyExc_Exception, "argument is not a UObject");
	}

	ue_PyUObject *py_obj = (ue_PyUObject *)obj;

	if (!py_obj->ue_object->IsA<UClass>())
	{
		return PyErr_Format(PyExc_Exception, "argument is not a UClass");
	}

	UClass *u_class = (UClass *)py_obj->ue_object;

	if (!u_class->IsChildOf<UActorComponent>())
	{
		return PyErr_Format(PyExc_Exception, "argument is not a UClass derived from UActorComponent");
	}

	USceneComponent *parent_component = nullptr;

	if (py_parent)
	{
		parent_component = ue_py_check_type<USceneComponent>(py_parent);
		if (!parent_component)
		{
			return PyErr_Format(PyExc_Exception, "argument is not a USceneComponent");
		}
	}

	UActorComponent *component = NewObject<UActorComponent>(actor, u_class, FName(UTF8_TO_TCHAR(name)), RF_Public);
	if (!component)
		return PyErr_Format(PyExc_Exception, "unable to create component");

	if (py_parent && component->IsA<USceneComponent>())
	{
		USceneComponent *scene_component = (USceneComponent *)component;
		scene_component->SetupAttachment(parent_component);
	}

	if (actor->GetWorld() && !component->IsRegistered())
	{
		component->RegisterComponent();
	}

	if (component->bWantsInitializeComponent && !component->HasBeenInitialized() && component->IsRegistered())
		component->InitializeComponent();

	Py_RETURN_UOBJECT(component);
}
Ejemplo n.º 8
0
UActorComponent* AActor::AddComponent(FName TemplateName, bool bManualAttachment, const FTransform& RelativeTransform, const UObject* ComponentTemplateContext)
{
	UActorComponent* Template = NULL;
	UBlueprintGeneratedClass* BlueprintGeneratedClass = Cast<UBlueprintGeneratedClass>((ComponentTemplateContext != NULL) ? ComponentTemplateContext->GetClass() : GetClass());
	while(BlueprintGeneratedClass != NULL)
	{
		Template = BlueprintGeneratedClass->FindComponentTemplateByName(TemplateName);
		if(NULL != Template)
		{
			break;
		}
		BlueprintGeneratedClass = Cast<UBlueprintGeneratedClass>(BlueprintGeneratedClass->GetSuperClass());
	}

	UActorComponent* NewActorComp = CreateComponentFromTemplate(Template);
	if(NewActorComp != NULL)
	{
		// The user has the option of doing attachment manually where they have complete control or via the automatic rule
		// that the first component added becomes the root component, with subsequent components attached to the root.
		USceneComponent* NewSceneComp = Cast<USceneComponent>(NewActorComp);
		bool bDeferRegisterStaticComponent = false;
		EComponentMobility::Type OriginalMobility = EComponentMobility::Movable;

		if(NewSceneComp != NULL)
		{
			// Components with Mobility set to EComponentMobility::Static or EComponentMobility::Stationary can't be properly set up in UCS (all changes will be rejected
			// due to EComponentMobility::Static flag) so we're going to temporarily change the flag and defer the registration until UCS has finished.
			bDeferRegisterStaticComponent = bRunningUserConstructionScript && NewSceneComp->Mobility != EComponentMobility::Movable;
			OriginalMobility = NewSceneComp->Mobility;
			if (bDeferRegisterStaticComponent)
			{
				NewSceneComp->Mobility = EComponentMobility::Movable;
			}

			if (!bManualAttachment)
			{
				if (RootComponent == NULL)
				{
					RootComponent = NewSceneComp;
				}
				else
				{
					NewSceneComp->AttachTo(RootComponent);
				}
			}

			NewSceneComp->SetRelativeTransform(RelativeTransform);
		}

		// Call function to notify component it has been created
		NewActorComp->OnComponentCreated();

		if (bDeferRegisterStaticComponent)
		{
			// Defer registration until after UCS has completed.
			FDeferRegisterStaticComponents::Get().DeferStaticComponent(this, NewSceneComp, OriginalMobility);
		}
		else
		{
			// Register component, which will create physics/rendering state, now component is in correct position
			NewActorComp->RegisterComponent();
		}
	}

	return NewActorComp;
}