USceneComponent* FComponentEditorUtils::GetSceneComponent( UObject* Object, UObject* SubObject /*= NULL*/ ) { if( Object ) { AActor* Actor = Cast<AActor>( Object ); if( Actor ) { if( SubObject ) { if( SubObject->HasAnyFlags( RF_DefaultSubObject ) ) { UObject* ClassDefaultObject = SubObject->GetOuter(); if( ClassDefaultObject ) { for( TFieldIterator<UObjectProperty> ObjPropIt( ClassDefaultObject->GetClass() ); ObjPropIt; ++ObjPropIt ) { UObjectProperty* ObjectProperty = *ObjPropIt; if( SubObject == ObjectProperty->GetObjectPropertyValue_InContainer( ClassDefaultObject ) ) { return CastChecked<USceneComponent>( ObjectProperty->GetObjectPropertyValue_InContainer( Actor ) ); } } } } else if( UBlueprint* Blueprint = Cast<UBlueprint>( SubObject->GetOuter() ) ) { if( Blueprint->SimpleConstructionScript ) { TArray<USCS_Node*> SCSNodes = Blueprint->SimpleConstructionScript->GetAllNodes(); for( int32 SCSNodeIndex = 0; SCSNodeIndex < SCSNodes.Num(); ++SCSNodeIndex ) { USCS_Node* SCS_Node = SCSNodes[ SCSNodeIndex ]; if( SCS_Node && SCS_Node->ComponentTemplate == SubObject ) { return SCS_Node->GetParentComponentTemplate( Blueprint ); } } } } } return Actor->GetRootComponent(); } else if( Object->IsA<USceneComponent>() ) { return CastChecked<USceneComponent>( Object ); } } return NULL; }
void UComponentDelegateBinding::BindDynamicDelegates(AActor* InInstance) const { for(int32 BindIdx=0; BindIdx<ComponentDelegateBindings.Num(); BindIdx++) { const FBlueprintComponentDelegateBinding& Binding = ComponentDelegateBindings[BindIdx]; // Get the function we want to bind UFunction* FunctionToBind = FindField<UFunction>(InInstance->GetClass(), Binding.FunctionNameToBind); // Get the property that points to the component we want to assign to UObjectProperty* ObjProp = FindField<UObjectProperty>(InInstance->GetClass(), Binding.ComponentPropertyName); // If we have both of those.. if(ObjProp != NULL && FunctionToBind != NULL) { // ..see if there is actually a component assigned UActorComponent* Component = Cast<UActorComponent>(ObjProp->GetObjectPropertyValue_InContainer(InInstance)); if(Component != NULL) { // If there is, find the delegate property on it UMulticastDelegateProperty* DelegateProp = FindField<UMulticastDelegateProperty>(Component->GetClass(), Binding.DelegatePropertyName); if(DelegateProp) { // Found that, finally bind function on the actor to this delegate FMulticastScriptDelegate* TargetDelegate = DelegateProp->GetPropertyValuePtr_InContainer(Component); FScriptDelegate Delegate; Delegate.SetFunctionName(Binding.FunctionNameToBind); Delegate.SetObject(InInstance); TargetDelegate->AddUnique(Delegate); } } } } }
UK2Node_VariableGet* UGameplayAbilityGraphSchema::SpawnVariableGetNode(const FVector2D GraphPosition, class UEdGraph* ParentGraph, FName VariableName, UStruct* Source) const { // Perform handling to create custom nodes for some classes UProperty* VarProp = FindField<UProperty>(Source, VariableName); UObjectProperty* ObjProp = Cast<UObjectProperty>(VarProp); if (ObjProp) { UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraph(ParentGraph); TSubclassOf<UObject> GenClass = Blueprint->GeneratedClass; UObject* ActiveObject = GenClass->GetDefaultObject(); // If the variable is a GameplayEffect create a custom node to show it FString PropType; ObjProp->GetCPPMacroType(PropType); if (PropType == "UGameplayEffect") { UK2Node_GameplayEffectVariable* NodeTemplate = NewObject<UK2Node_GameplayEffectVariable>(); UEdGraphSchema_K2::ConfigureVarNode(NodeTemplate, VariableName, Source, Blueprint); UK2Node_GameplayEffectVariable* VariableNode = FEdGraphSchemaAction_K2NewNode::SpawnNodeFromTemplate<UK2Node_GameplayEffectVariable>(ParentGraph, NodeTemplate, GraphPosition); UGameplayEffect* GameplayEffect = Cast<UGameplayEffect>(ObjProp->GetObjectPropertyValue_InContainer(ActiveObject)); if (GameplayEffect) { VariableNode->GameplayEffect = GameplayEffect; } return VariableNode; } } // Couldn't find an appropriate custom node for this variable, use the generic case return Super::SpawnVariableGetNode(GraphPosition, ParentGraph, VariableName, Source); }
void SKismetInspector::UpdateFromObjects(const TArray<UObject*>& PropertyObjects, struct FKismetSelectionInfo& SelectionInfo, const FShowDetailsOptions& Options) { // If we're using the unified blueprint editor, there's not an explicit point where // we ender a kind of component editing mode, so instead, just look at what we're selecting. // If we select a component, then enable the customization. if ( GetDefault<UEditorExperimentalSettings>()->bUnifiedBlueprintEditor ) { bool bEnableComponentCustomization = false; TSharedPtr<FBlueprintEditor> BlueprintEditor = BlueprintEditorPtr.Pin(); if ( BlueprintEditor.IsValid() ) { if ( BlueprintEditor->CanAccessComponentsMode() ) { for ( UObject* PropertyObject : PropertyObjects ) { if ( PropertyObject->IsA<UActorComponent>() ) { bEnableComponentCustomization = true; break; } } } } EnableComponentDetailsCustomization(bEnableComponentCustomization); } PropertyView->OnFinishedChangingProperties().Clear(); PropertyView->OnFinishedChangingProperties().Add( UserOnFinishedChangingProperties ); if (!Options.bForceRefresh) { // Early out if the PropertyObjects and the SelectedObjects are the same bool bEquivalentSets = (PropertyObjects.Num() == SelectedObjects.Num()); if (bEquivalentSets) { // Verify the elements of the sets are equivalent for (int32 i = 0; i < PropertyObjects.Num(); i++) { if (PropertyObjects[i] != SelectedObjects[i].Get()) { bEquivalentSets = false; break; } } } if (bEquivalentSets) { return; } } // Proceed to update SelectedObjects.Empty(); for (auto ObjectIt = PropertyObjects.CreateConstIterator(); ObjectIt; ++ObjectIt) { if (UObject* Object = *ObjectIt) { if (!Object->IsValidLowLevel()) { ensureMsg(false, TEXT("Object in KismetInspector is invalid, see TTP 281915")); continue; } SelectedObjects.Add(Object); if (USCS_Node* SCSNode = Cast<USCS_Node>(Object)) { // Edit the component template UActorComponent* NodeComponent = SCSNode->ComponentTemplate; if (NodeComponent != NULL) { SelectionInfo.ObjectsForPropertyEditing.Add(NodeComponent); SelectionInfo.EditableComponentTemplates.Add(NodeComponent); } } else if (UK2Node* K2Node = Cast<UK2Node>(Object)) { // Edit the component template if it exists if (UActorComponent* Template = K2Node->GetTemplateFromNode()) { SelectionInfo.ObjectsForPropertyEditing.Add(Template); SelectionInfo.EditableComponentTemplates.Add(Template); } // See if we should edit properties of the node if (K2Node->ShouldShowNodeProperties()) { SelectionInfo.ObjectsForPropertyEditing.Add(Object); } } else if (UActorComponent* ActorComponent = Cast<UActorComponent>(Object)) { AActor* Owner = ActorComponent->GetOwner(); if(Owner != NULL && Owner->HasAnyFlags(RF_ClassDefaultObject)) { // We're editing a component that's owned by a CDO, so set the CDO to the property editor (so that propagation works) and then filter to just the component property that we want to edit SelectionInfo.ObjectsForPropertyEditing.AddUnique(Owner); SelectionInfo.EditableComponentTemplates.Add(ActorComponent); } else { // We're editing a component that exists outside of a CDO, so just edit the component instance directly SelectionInfo.ObjectsForPropertyEditing.AddUnique(ActorComponent); } } else { // Editing any UObject* SelectionInfo.ObjectsForPropertyEditing.AddUnique(Object); } } } // By default, no property filtering SelectedObjectProperties.Empty(); // Add to the property filter list for any editable component templates if(SelectionInfo.EditableComponentTemplates.Num()) { for(auto CompIt = SelectionInfo.EditableComponentTemplates.CreateIterator(); CompIt; ++CompIt) { UActorComponent* EditableComponentTemplate = *CompIt; check(EditableComponentTemplate != NULL); // Add all properties belonging to the component template class for(TFieldIterator<UProperty> PropIt(EditableComponentTemplate->GetClass()); PropIt; ++PropIt) { UProperty* Property = *PropIt; check(Property != NULL); AddPropertiesRecursive(Property); } // Attempt to locate a matching property for the current component template for(auto ObjIt = SelectionInfo.ObjectsForPropertyEditing.CreateIterator(); ObjIt; ++ObjIt) { UObject* Object = *ObjIt; check(Object != NULL); if(Object != EditableComponentTemplate) { for(TFieldIterator<UObjectProperty> ObjPropIt(Object->GetClass()); ObjPropIt; ++ObjPropIt) { UObjectProperty* ObjectProperty = *ObjPropIt; check(ObjectProperty != NULL); // If the property value matches the current component template, add it as a selected property for filtering if(EditableComponentTemplate == ObjectProperty->GetObjectPropertyValue_InContainer(Object)) { SelectedObjectProperties.Add(ObjectProperty); } } } } } } PropertyViewTitle = Options.ForcedTitle; bShowComponents = Options.bShowComponents; // Update our context-sensitive editing widget ContextualEditingBorderWidget->SetContent( MakeContextualEditingWidget(SelectionInfo, Options) ); }