void FPathContextMenu::GetPackageNamesInSelectedPaths(TArray<FString>& OutPackageNames) const { // Load the asset registry module FAssetRegistryModule& AssetRegistryModule = FModuleManager::Get().LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry")); // Form a filter from the paths FARFilter Filter; Filter.bRecursivePaths = true; for (int32 PathIdx = 0; PathIdx < SelectedPaths.Num(); ++PathIdx) { const FString& Path = SelectedPaths[PathIdx]; new (Filter.PackagePaths) FName(*Path); } // Query for a list of assets in the selected paths TArray<FAssetData> AssetList; AssetRegistryModule.Get().GetAssets(Filter, AssetList); // Form a list of unique package names from the assets TSet<FName> UniquePackageNames; for (int32 AssetIdx = 0; AssetIdx < AssetList.Num(); ++AssetIdx) { UniquePackageNames.Add(AssetList[AssetIdx].PackageName); } // Add all unique package names to the output for ( auto PackageIt = UniquePackageNames.CreateConstIterator(); PackageIt; ++PackageIt ) { OutPackageNames.Add( (*PackageIt).ToString() ); } }
bool FPropertyEditorToolkit::IsExposedAsColumn( const TWeakPtr< IPropertyTreeRow >& Row ) const { bool Result = false; if (Row.IsValid()) { const TSharedPtr< FPropertyPath > RowPathPtr = Row.Pin()->GetPropertyPath(); if ( RowPathPtr.IsValid() ) { TSharedRef< FPropertyPath > TrimmedPath = RowPathPtr->TrimRoot( PropertyTable->GetRootPath()->GetNumProperties() ); const TSet< TSharedRef< IPropertyTableRow > > SelectedRows = PropertyTable->GetSelectedRows(); for( auto RowIter = SelectedRows.CreateConstIterator(); RowIter; ++RowIter ) { TrimmedPath = TrimmedPath->TrimRoot( (*RowIter)->GetPartialPath()->GetNumProperties() ); break; } for (int Index = 0; Index < PropertyPathsAddedAsColumns.Num(); Index++) { if ( FPropertyPath::AreEqual( TrimmedPath, PropertyPathsAddedAsColumns[ Index ] ) ) { Result = true; break; } } } } return Result; }
void UEdGraphSchema::BreakPinLinks(UEdGraphPin& TargetPin, bool bSendsNodeNotifcation) const { #if WITH_EDITOR // Copy the old pin links TArray<class UEdGraphPin*> OldLinkedTo(TargetPin.LinkedTo); #endif TargetPin.BreakAllPinLinks(); #if WITH_EDITOR TSet<UEdGraphNode*> NodeList; // Notify this node TargetPin.GetOwningNode()->PinConnectionListChanged(&TargetPin); NodeList.Add(TargetPin.GetOwningNode()); // As well as all other nodes that were connected for (TArray<UEdGraphPin*>::TIterator PinIt(OldLinkedTo); PinIt; ++PinIt) { UEdGraphPin* OtherPin = *PinIt; UEdGraphNode* OtherNode = OtherPin->GetOwningNode(); OtherNode->PinConnectionListChanged(OtherPin); NodeList.Add(OtherNode); } if (bSendsNodeNotifcation) { // Send all nodes that received a new pin connection a notification for (auto It = NodeList.CreateConstIterator(); It; ++It) { UEdGraphNode* Node = (*It); Node->NodeConnectionListChanged(); } } #endif //#if WITH_EDITOR }
// Update the drawing policy with the set of hovered pins (which can be empty) void FConnectionDrawingPolicy::SetHoveredPins(const TSet< TWeakObjectPtr<UEdGraphPin> >& InHoveredPins, const TArray< TSharedPtr<SGraphPin> >& OverridePins, double HoverTime) { HoveredPins.Empty(); LastHoverTimeEvent = (OverridePins.Num() > 0) ? 0.0 : HoverTime; for (auto PinIt = OverridePins.CreateConstIterator(); PinIt; ++PinIt) { if (SGraphPin* GraphPin = PinIt->Get()) { HoveredPins.Add(GraphPin->GetPinObj()); } } // Convert the widget pointer for hovered pins to be EdGraphPin pointers for their connected nets (both ends of any connection) for (auto PinIt = InHoveredPins.CreateConstIterator(); PinIt; ++PinIt) { if (UEdGraphPin* Pin = PinIt->Get()) { if (Pin->LinkedTo.Num() > 0) { HoveredPins.Add(Pin); for (auto LinkIt = Pin->LinkedTo.CreateConstIterator(); LinkIt; ++LinkIt) { HoveredPins.Add(*LinkIt); } } } } }
void FKismetConnectionDrawingPolicy::ResetIncompatiblePinDrawState(const TSet< TSharedRef<SWidget> >& VisiblePins) { for(auto VisiblePinIterator = VisiblePins.CreateConstIterator(); VisiblePinIterator; ++VisiblePinIterator) { TSharedPtr<SGraphPin> VisiblePin = StaticCastSharedRef<SGraphPin>(*VisiblePinIterator); VisiblePin->SetPinColorModifier(FLinearColor::White); } }
void FPropertyEditorToolkit::ToggleColumnForProperty( const TSharedPtr< FPropertyPath >& PropertyPath ) { if ( !PropertyPath.IsValid() ) { return; } TSharedRef< FPropertyPath > NewPath = PropertyPath->TrimRoot( PropertyTable->GetRootPath()->GetNumProperties() ); const TSet< TSharedRef< IPropertyTableRow > > SelectedRows = PropertyTable->GetSelectedRows(); for( auto RowIter = SelectedRows.CreateConstIterator(); RowIter; ++RowIter ) { NewPath = NewPath->TrimRoot( (*RowIter)->GetPartialPath()->GetNumProperties() ); break; } if ( NewPath->GetNumProperties() == 0 ) { return; } TSharedPtr< IPropertyTableColumn > ExistingColumn; for( auto ColumnIter = PropertyTable->GetColumns().CreateConstIterator(); ColumnIter; ++ColumnIter ) { TSharedRef< IPropertyTableColumn > Column = *ColumnIter; const TSharedPtr< FPropertyPath > Path = Column->GetDataSource()->AsPropertyPath(); if ( Path.IsValid() && FPropertyPath::AreEqual( Path.ToSharedRef(), NewPath ) ) { ExistingColumn = Column; } } if ( ExistingColumn.IsValid() ) { PropertyTable->RemoveColumn( ExistingColumn.ToSharedRef() ); const TSharedRef< FPropertyPath > ColumnPath = ExistingColumn->GetDataSource()->AsPropertyPath().ToSharedRef(); for (int Index = PropertyPathsAddedAsColumns.Num() - 1; Index >= 0 ; Index--) { if ( FPropertyPath::AreEqual( ColumnPath, PropertyPathsAddedAsColumns[ Index ] ) ) { PropertyPathsAddedAsColumns.RemoveAt( Index ); } } } else { PropertyTable->AddColumn( NewPath ); PropertyPathsAddedAsColumns.Add( NewPath ); } }
void FKismetConnectionDrawingPolicy::SetIncompatiblePinDrawState(const TSharedPtr<SGraphPin>& StartPin, const TSet< TSharedRef<SWidget> >& VisiblePins) { ResetIncompatiblePinDrawState(VisiblePins); for(auto VisiblePinIterator = VisiblePins.CreateConstIterator(); VisiblePinIterator; ++VisiblePinIterator) { TSharedPtr<SGraphPin> CheckPin = StaticCastSharedRef<SGraphPin>(*VisiblePinIterator); if(CheckPin != StartPin) { const FPinConnectionResponse Response = StartPin->GetPinObj()->GetSchema()->CanCreateConnection(StartPin->GetPinObj(), CheckPin->GetPinObj()); if(Response.Response == CONNECT_RESPONSE_DISALLOW) { CheckPin->SetPinColorModifier(FLinearColor(0.25f, 0.25f, 0.25f, 0.5f)); } } } }
FReply FDragConnection::DroppedOnPin(FVector2D ScreenPosition, FVector2D GraphPosition) { TArray<UEdGraphPin*> ValidSourcePins; ValidateGraphPinList(/*out*/ ValidSourcePins); const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "GraphEd_CreateConnection", "Create Pin Link") ); UEdGraphPin* PinB = GetHoveredPin(); bool bError = false; TSet<UEdGraphNode*> NodeList; for (UEdGraphPin* PinA : ValidSourcePins) { if ((PinA != NULL) && (PinB != NULL)) { UEdGraph* MyGraphObj = PinA->GetOwningNode()->GetGraph(); if (MyGraphObj->GetSchema()->TryCreateConnection(PinA, PinB)) { NodeList.Add(PinA->GetOwningNode()); NodeList.Add(PinB->GetOwningNode()); } } else { bError = true; } } // Send all nodes that received a new pin connection a notification for (auto It = NodeList.CreateConstIterator(); It; ++It) { UEdGraphNode* Node = (*It); Node->NodeConnectionListChanged(); } if (bError) { return FReply::Unhandled(); } return FReply::Handled(); }
void UEdGraphNode::BreakAllNodeLinks() { TSet<UEdGraphNode*> NodeList; NodeList.Add(this); // Iterate over each pin and break all links for(int32 PinIdx=0; PinIdx<Pins.Num(); PinIdx++) { Pins[PinIdx]->BreakAllPinLinks(); NodeList.Add(Pins[PinIdx]->GetOwningNode()); } // Send all nodes that received a new pin connection a notification for (auto It = NodeList.CreateConstIterator(); It; ++It) { UEdGraphNode* Node = (*It); Node->NodeConnectionListChanged(); } }
void FPropertyEditorToolkit::GridSelectionChanged() { TArray< TWeakObjectPtr< UObject > > SelectedObjects; PropertyTable->GetSelectedObjects( SelectedObjects ); PropertyTree->SetObjectArray( SelectedObjects ); const TSet< TSharedRef< IPropertyTableRow > > SelectedRows = PropertyTable->GetSelectedRows(); if ( SelectedRows.Num() == 1 ) { for( auto RowIter = SelectedRows.CreateConstIterator(); RowIter; ++RowIter ) { PropertyTree->SetRootPath( PropertyTable->GetRootPath()->ExtendPath( (*RowIter)->GetPartialPath() ) ); break; } } else if ( !FPropertyPath::AreEqual( PropertyTree->GetRootPath(), PropertyTable->GetRootPath() ) ) { PropertyTree->SetRootPath( PropertyTable->GetRootPath() ); } }
void USoundCueGraphNode_Base::AutowireNewNode(UEdGraphPin* FromPin) { if (FromPin != NULL) { const USoundCueGraphSchema* Schema = CastChecked<USoundCueGraphSchema>(GetSchema()); TSet<UEdGraphNode*> NodeList; // auto-connect from dragged pin to first compatible pin on the new node for (int32 i=0; i<Pins.Num(); i++) { UEdGraphPin* Pin = Pins[i]; check(Pin); FPinConnectionResponse Response = Schema->CanCreateConnection(FromPin, Pin); if (ECanCreateConnectionResponse::CONNECT_RESPONSE_MAKE == Response.Response) { if (Schema->TryCreateConnection(FromPin, Pin)) { NodeList.Add(FromPin->GetOwningNode()); NodeList.Add(this); } break; } else if(ECanCreateConnectionResponse::CONNECT_RESPONSE_BREAK_OTHERS_A == Response.Response) { InsertNewNode(FromPin, Pin, NodeList); break; } } // Send all nodes that received a new pin connection a notification for (auto It = NodeList.CreateConstIterator(); It; ++It) { UEdGraphNode* Node = (*It); Node->NodeConnectionListChanged(); } } }
void UEdGraphSchema::BreakNodeLinks(UEdGraphNode& TargetNode) const { #if WITH_EDITOR TSet<UEdGraphNode*> NodeList; NodeList.Add(&TargetNode); // Iterate over each pin and break all links for (TArray<UEdGraphPin*>::TIterator PinIt(TargetNode.Pins); PinIt; ++PinIt) { UEdGraphPin* TargetPin = *PinIt; if (TargetPin) { // Keep track of which node(s) the pin's connected to for (auto OtherPin : TargetPin->LinkedTo) { if (OtherPin) { UEdGraphNode* OtherNode = OtherPin->GetOwningNode(); if (OtherNode) { NodeList.Add(OtherNode); } } } BreakPinLinks(*TargetPin, false); } } // Send all nodes that lost connections a notification for (auto It = NodeList.CreateConstIterator(); It; ++It) { UEdGraphNode* Node = (*It); Node->NodeConnectionListChanged(); } #endif //#if WITH_EDITOR }
void UK2Node::AutowireNewNode(UEdGraphPin* FromPin) { const UEdGraphSchema_K2* K2Schema = CastChecked<UEdGraphSchema_K2>(GetSchema()); // Do some auto-connection if (FromPin != NULL) { TSet<UEdGraphNode*> NodeList; // sometimes we don't always find an ideal connection, but we want to exhaust // all our options first... this stores a secondary less-ideal pin to connect to, if nothing better was found UEdGraphPin* BackupConnection = NULL; // If not dragging an exec pin, auto-connect from dragged pin to first compatible pin on the new node for (int32 i=0; i<Pins.Num(); i++) { UEdGraphPin* Pin = Pins[i]; check(Pin); ECanCreateConnectionResponse ConnectResponse = K2Schema->CanCreateConnection(FromPin, Pin).Response; if (ConnectResponse == ECanCreateConnectionResponse::CONNECT_RESPONSE_MAKE) { if (K2Schema->TryCreateConnection(FromPin, Pin)) { NodeList.Add(FromPin->GetOwningNode()); NodeList.Add(this); } // null out the backup connection (so we don't attempt to make it // once we exit the loop... we successfully made this connection!) BackupConnection = NULL; break; } else if((FromPin->PinType.PinCategory == K2Schema->PC_Exec) && (ConnectResponse == ECanCreateConnectionResponse::CONNECT_RESPONSE_BREAK_OTHERS_A)) { InsertNewNode(FromPin, Pin, NodeList); // null out the backup connection (so we don't attempt to make it // once we exit the loop... we successfully made this connection!) BackupConnection = NULL; break; } else if ((BackupConnection == NULL) && (ConnectResponse == ECanCreateConnectionResponse::CONNECT_RESPONSE_MAKE_WITH_CONVERSION_NODE)) { // save this off, in-case we don't make any connection at all BackupConnection = Pin; } } // if we didn't find an ideal connection, then lets connect this pin to // the BackupConnection (something, like a connection that requires a conversion node, etc.) if ((BackupConnection != NULL) && K2Schema->TryCreateConnection(FromPin, BackupConnection)) { NodeList.Add(FromPin->GetOwningNode()); NodeList.Add(this); } // If we were not dragging an exec pin, but it was an output pin, try and connect the Then and Execute pins if ((FromPin->PinType.PinCategory != K2Schema->PC_Exec && FromPin->Direction == EGPD_Output)) { UEdGraphNode* FromPinNode = FromPin->GetOwningNode(); UEdGraphPin* FromThenPin = FromPinNode->FindPin(K2Schema->PN_Then); UEdGraphPin* ToExecutePin = FindPin(K2Schema->PN_Execute); if ((FromThenPin != NULL) && (FromThenPin->LinkedTo.Num() == 0) && (ToExecutePin != NULL) && K2Schema->ArePinsCompatible(FromThenPin, ToExecutePin, NULL)) { if (K2Schema->TryCreateConnection(FromThenPin, ToExecutePin)) { NodeList.Add(FromPinNode); NodeList.Add(this); } } } // Send all nodes that received a new pin connection a notification for (auto It = NodeList.CreateConstIterator(); It; ++It) { UEdGraphNode* Node = (*It); Node->NodeConnectionListChanged(); } } }
void SDetailsViewBase::QueryCustomDetailLayout(FDetailLayoutBuilderImpl& CustomDetailLayout) { FPropertyEditorModule& ParentPlugin = FModuleManager::GetModuleChecked<FPropertyEditorModule>("PropertyEditor"); // Get the registered classes that customize details FCustomDetailLayoutNameMap& GlobalCustomLayoutNameMap = ParentPlugin.ClassNameToDetailLayoutNameMap; UStruct* BaseStruct = GetBaseStruct(); // All the current customization instances need to be deleted when it is safe CustomizationClassInstancesPendingDelete = CustomizationClassInstances; CustomizationClassInstances.Empty(); //Ask for generic details not specific to an object being viewed if (GenericLayoutDelegate.IsBound()) { // Create a new instance of the custom detail layout for the current class TSharedRef<IDetailCustomization> CustomizationInstance = GenericLayoutDelegate.Execute(); // Ask for details immediately CustomizationInstance->CustomizeDetails(CustomDetailLayout); // Save the instance from destruction until we refresh CustomizationClassInstances.Add(CustomizationInstance); } // Sort them by query order. @todo not good enough struct FCompareFDetailLayoutCallback { FORCEINLINE bool operator()(const FDetailLayoutCallback& A, const FDetailLayoutCallback& B) const { return A.Order < B.Order; } }; TMap< TWeakObjectPtr<UStruct>, FDetailLayoutCallback*> FinalCallbackMap; for (auto ClassIt = ClassesWithProperties.CreateConstIterator(); ClassIt; ++ClassIt) { // Check the instanced map first FDetailLayoutCallback* Callback = InstancedClassToDetailLayoutMap.Find(*ClassIt); if (!Callback) { // callback wasn't found in the per instance map, try the global instances instead Callback = GlobalCustomLayoutNameMap.Find((*ClassIt)->GetFName()); } if (Callback) { FinalCallbackMap.Add(*ClassIt, Callback); } } FinalCallbackMap.ValueSort(FCompareFDetailLayoutCallback()); TSet<UStruct*> QueriedClasses; if (FinalCallbackMap.Num() > 0) { // Ask each class that we have properties for to customize its layout for (auto LayoutIt(FinalCallbackMap.CreateConstIterator()); LayoutIt; ++LayoutIt) { const TWeakObjectPtr<UStruct> WeakClass = LayoutIt.Key(); if (WeakClass.IsValid()) { UStruct* Class = WeakClass.Get(); FClassInstanceToPropertyMap& InstancedPropertyMap = ClassToPropertyMap.FindChecked(Class->GetFName()); for (FClassInstanceToPropertyMap::TIterator InstanceIt(InstancedPropertyMap); InstanceIt; ++InstanceIt) { FName Key = InstanceIt.Key(); CustomDetailLayout.SetCurrentCustomizationClass(CastChecked<UClass>(Class), Key); const FOnGetDetailCustomizationInstance& DetailDelegate = LayoutIt.Value()->DetailLayoutDelegate; if (DetailDelegate.IsBound()) { QueriedClasses.Add(Class); // Create a new instance of the custom detail layout for the current class TSharedRef<IDetailCustomization> CustomizationInstance = DetailDelegate.Execute(); // Ask for details immediately CustomizationInstance->CustomizeDetails(CustomDetailLayout); // Save the instance from destruction until we refresh CustomizationClassInstances.Add(CustomizationInstance); } } } } } // Ensure that the base class and its parents are always queried TSet<UStruct*> ParentClassesToQuery; if (BaseStruct && !QueriedClasses.Contains(BaseStruct)) { ParentClassesToQuery.Add(BaseStruct); ClassesWithProperties.Add(BaseStruct); } // Find base classes of queried classes that were not queried and add them to the query list // this supports cases where a parent class has no properties but still wants to add customization for (auto QueriedClassIt = ClassesWithProperties.CreateConstIterator(); QueriedClassIt; ++QueriedClassIt) { UStruct* ParentStruct = (*QueriedClassIt)->GetSuperStruct(); while (ParentStruct && ParentStruct->IsA(UClass::StaticClass()) && !QueriedClasses.Contains(ParentStruct) && !ClassesWithProperties.Contains(ParentStruct)) { ParentClassesToQuery.Add(ParentStruct); ParentStruct = ParentStruct->GetSuperStruct(); } } // Query extra base classes for (auto ParentIt = ParentClassesToQuery.CreateConstIterator(); ParentIt; ++ParentIt) { if (Cast<UClass>(*ParentIt)) { QueryLayoutForClass(CustomDetailLayout, *ParentIt); } } }