void FMaterialEditorUtilities::AddMaterialExpressionCategory(FGraphActionMenuBuilder& ActionMenuBuilder, FString CategoryName, TArray<struct FMaterialExpression>* MaterialExpressions, bool bMaterialFunction) { // Get type of dragged pin uint32 FromPinType = 0; if (ActionMenuBuilder.FromPin) { FromPinType = UMaterialGraphSchema::GetMaterialValueType(ActionMenuBuilder.FromPin); } for (int32 Index = 0; Index < MaterialExpressions->Num(); ++Index) { const FMaterialExpression& MaterialExpression = (*MaterialExpressions)[Index]; if (IsAllowedExpressionType(MaterialExpression.MaterialClass, bMaterialFunction)) { if (!ActionMenuBuilder.FromPin || HasCompatibleConnection(MaterialExpression.MaterialClass, FromPinType, ActionMenuBuilder.FromPin->Direction, bMaterialFunction)) { FFormatNamedArguments Arguments; Arguments.Add(TEXT("Name"), FText::FromString( *MaterialExpression.Name )); const FText ToolTip = FText::Format( LOCTEXT( "NewMaterialExpressionTooltip", "Adds a {Name} node here" ), Arguments ); TSharedPtr<FMaterialGraphSchemaAction_NewNode> NewNodeAction(new FMaterialGraphSchemaAction_NewNode( CategoryName, FText::FromString(MaterialExpression.Name), ToolTip.ToString(), 0)); ActionMenuBuilder.AddAction(NewNodeAction); NewNodeAction->MaterialExpressionClass = MaterialExpression.MaterialClass; NewNodeAction->Keywords = CastChecked<UMaterialExpression>(MaterialExpression.MaterialClass->GetDefaultObject())->GetKeywords(); } } } }
void UMaterialGraphSchema::GetCommentAction(FGraphActionMenuBuilder& ActionMenuBuilder, const UEdGraph* CurrentGraph) const { if (!ActionMenuBuilder.FromPin) { const bool bIsManyNodesSelected = CurrentGraph ? (FMaterialEditorUtilities::GetNumberOfSelectedNodes(CurrentGraph) > 0) : false; const FText CommentDesc = LOCTEXT("CommentDesc", "New Comment"); const FText MultiCommentDesc = LOCTEXT("MultiCommentDesc", "Create Comment from Selection"); const FText CommentToolTip = LOCTEXT("CommentToolTip", "Creates a comment."); const FText MenuDescription = bIsManyNodesSelected ? MultiCommentDesc : CommentDesc; TSharedPtr<FMaterialGraphSchemaAction_NewComment> NewAction(new FMaterialGraphSchemaAction_NewComment(TEXT(""), MenuDescription.ToString(), CommentToolTip.ToString(), 0)); ActionMenuBuilder.AddAction( NewAction ); } }
void UMaterialGraphSchema::GetMaterialFunctionActions(FGraphActionMenuBuilder& ActionMenuBuilder) const { // Load the asset registry module FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry")); // Collect a full list of assets with the specified class TArray<FAssetData> AssetDataList; AssetRegistryModule.Get().GetAssetsByClass(UMaterialFunction::StaticClass()->GetFName(), AssetDataList); for (int32 AssetIndex = 0; AssetIndex < AssetDataList.Num(); ++AssetIndex) { const FAssetData& AssetData = AssetDataList[AssetIndex]; const bool bExposeToLibrary = AssetData.TagsAndValues.FindRef("bExposeToLibrary") == TEXT("TRUE"); // If this was a function that was selected to be exposed to the library if ( bExposeToLibrary ) { if(AssetData.IsAssetLoaded()) { if(AssetData.GetAsset()->GetOutermost() == GetTransientPackage()) { continue; } } // Gather the relevant information from the asset data const FString FunctionPathName = AssetData.ObjectPath.ToString(); const FString Description = AssetData.TagsAndValues.FindRef("Description"); TArray<FString> LibraryCategories; { const FString LibraryCategoriesString = AssetData.TagsAndValues.FindRef("LibraryCategories"); if ( !LibraryCategoriesString.IsEmpty() ) { UArrayProperty* LibraryCategoriesProperty = FindFieldChecked<UArrayProperty>(UMaterialFunction::StaticClass(), TEXT("LibraryCategories")); uint8* DestAddr = (uint8*)(&LibraryCategories); LibraryCategoriesProperty->ImportText(*LibraryCategoriesString, DestAddr, PPF_None, NULL, GWarn); } if ( LibraryCategories.Num() == 0 ) { LibraryCategories.Add( LOCTEXT("UncategorizedMaterialFunction", "Uncategorized").ToString() ); } } // Extract the object name from the path FString FunctionName = FunctionPathName; int32 PeriodIndex = FunctionPathName.Find(TEXT("."), ESearchCase::CaseSensitive, ESearchDir::FromEnd); if (PeriodIndex != INDEX_NONE) { FunctionName = FunctionPathName.Right(FunctionPathName.Len() - PeriodIndex - 1); } // For each category the function should belong to... for (int32 CategoryIndex = 0; CategoryIndex < LibraryCategories.Num(); CategoryIndex++) { const FString& CategoryName = LibraryCategories[CategoryIndex]; TSharedPtr<FMaterialGraphSchemaAction_NewFunctionCall> NewFunctionAction(new FMaterialGraphSchemaAction_NewFunctionCall( CategoryName, FunctionName, Description, 0)); ActionMenuBuilder.AddAction(NewFunctionAction); NewFunctionAction->FunctionPath = FunctionPathName; } } } }