void SMaterialEditorViewport::OnSetPreviewMeshFromSelection() { bool bFoundPreviewMesh = false; FEditorDelegates::LoadSelectedAssetsIfNeeded.Broadcast(); UMaterialInterface* MaterialInterface = MaterialEditorPtr.Pin()->GetMaterialInterface(); // Look for a selected asset that can be converted to a mesh component for (FSelectionIterator SelectionIt(*GEditor->GetSelectedObjects()); SelectionIt && !bFoundPreviewMesh; ++SelectionIt) { UObject* TestAsset = *SelectionIt; if (TestAsset->IsAsset()) { if (TSubclassOf<UActorComponent> ComponentClass = FComponentAssetBrokerage::GetPrimaryComponentForAsset(TestAsset->GetClass())) { if (ComponentClass->IsChildOf(UMeshComponent::StaticClass())) { if (USkeletalMesh* SkeletalMesh = Cast<USkeletalMesh>(TestAsset)) { // Special case handling for skeletal meshes, sets the material to be usable with them if (MaterialInterface->GetMaterial()) { bool bNeedsRecompile = false; MaterialInterface->GetMaterial()->SetMaterialUsage(bNeedsRecompile, MATUSAGE_SkeletalMesh); } } SetPreviewAsset(TestAsset); MaterialInterface->PreviewMesh = TestAsset->GetPathName(); bFoundPreviewMesh = true; } } } } if (bFoundPreviewMesh) { FMaterialEditor::UpdateThumbnailInfoPreviewMesh(MaterialInterface); MaterialInterface->MarkPackageDirty(); RefreshViewport(); } else { FSuppressableWarningDialog::FSetupInfo Info(NSLOCTEXT("UnrealEd", "Warning_NoPreviewMeshFound_Message", "You need to select a mesh-based asset in the content browser to preview it."), NSLOCTEXT("UnrealEd", "Warning_NoPreviewMeshFound", "Warning: No Preview Mesh Found"), "Warning_NoPreviewMeshFound"); Info.ConfirmText = NSLOCTEXT("UnrealEd", "Warning_NoPreviewMeshFound_Confirm", "Continue"); FSuppressableWarningDialog NoPreviewMeshWarning( Info ); NoPreviewMeshWarning.ShowModal(); } }
virtual void HandleObjectReference(UObject*& InObject, const UObject* InReferencingObject, const UProperty* InReferencingProperty) override { UObject* Object = InObject; if (!Object || Object->IsA<UBlueprint>()) { return; } UClass* ActualClass = Cast<UClass>(Dependencies.GetActualStruct()); UStruct* CurrentlyConvertedStruct = ActualClass ? Dependencies.FindOriginalClass(ActualClass) : Dependencies.GetActualStruct(); ensure(CurrentlyConvertedStruct); if (Object == CurrentlyConvertedStruct) { return; } if (Object->HasAnyFlags(RF_ClassDefaultObject)) { // Static functions from libraries are called on CDO. (The functions is stored as a name not an object). UClass* OwnerClass = Object->GetClass(); if (OwnerClass && (OwnerClass != CurrentlyConvertedStruct)) { UBlueprintGeneratedClass* OwnerAsBPGC = Cast<UBlueprintGeneratedClass>(OwnerClass); if (OwnerAsBPGC && !Dependencies.ConvertedClasses.Contains(OwnerAsBPGC) && Dependencies.WillClassBeConverted(OwnerAsBPGC)) { Dependencies.ConvertedClasses.Add(OwnerAsBPGC); } } } const bool bUseZConstructorInGeneratedCode = false; //TODO: What About Delegates? auto ObjAsBPGC = Cast<UBlueprintGeneratedClass>(Object); const bool bWillBeConvetedAsBPGC = ObjAsBPGC && Dependencies.WillClassBeConverted(ObjAsBPGC); if (bWillBeConvetedAsBPGC) { if (ObjAsBPGC != CurrentlyConvertedStruct) { Dependencies.ConvertedClasses.Add(ObjAsBPGC); if(!bUseZConstructorInGeneratedCode) { IncludeTheHeaderInBody(ObjAsBPGC); } } } else if (UUserDefinedStruct* UDS = Cast<UUserDefinedStruct>(Object)) { if (!UDS->HasAnyFlags(RF_ClassDefaultObject)) { Dependencies.ConvertedStructs.Add(UDS); if(!bUseZConstructorInGeneratedCode) { IncludeTheHeaderInBody(UDS); } } } else if (UUserDefinedEnum* UDE = Cast<UUserDefinedEnum>(Object)) { if (!UDE->HasAnyFlags(RF_ClassDefaultObject)) { Dependencies.ConvertedEnum.Add(UDE); } } else if ((Object->IsAsset() || ObjAsBPGC) && !Object->IsIn(CurrentlyConvertedStruct)) { // include all not converted super classes for (auto SuperBPGC = ObjAsBPGC ? Cast<UBlueprintGeneratedClass>(ObjAsBPGC->GetSuperClass()) : nullptr; SuperBPGC && !Dependencies.WillClassBeConverted(SuperBPGC); SuperBPGC = Cast<UBlueprintGeneratedClass>(SuperBPGC->GetSuperClass())) { Dependencies.Assets.AddUnique(SuperBPGC); } Dependencies.Assets.AddUnique(Object); return; } else if (auto ObjAsClass = Cast<UClass>(Object)) { if (ObjAsClass->HasAnyClassFlags(CLASS_Native)) { return; } } else if (Object->IsA<UScriptStruct>()) { return; } FindReferencesForNewObject(Object); }
virtual void HandleObjectReference(UObject*& InObject, const UObject* InReferencingObject, const UProperty* InReferencingProperty) override { UObject* Object = InObject; if (!Object || Object->IsA<UBlueprint>()) { return; } UClass* ActualClass = Cast<UClass>(Dependencies.GetActualStruct()); UStruct* CurrentlyConvertedStruct = ActualClass ? Dependencies.FindOriginalClass(ActualClass) : Dependencies.GetActualStruct(); ensure(CurrentlyConvertedStruct); if (Object == CurrentlyConvertedStruct) { return; } { auto ObjAsField = Cast<UField>(Object); if (!ObjAsField) { const bool bTransientObject = (Object->HasAnyFlags(RF_Transient) && !Object->IsIn(CurrentlyConvertedStruct)) || Object->IsIn(GetTransientPackage()); if (bTransientObject) { return; } ObjAsField = Object->GetClass(); } if (ObjAsField && !ObjAsField->HasAnyFlags(RF_ClassDefaultObject)) { if (ObjAsField->IsA<UProperty>()) { ObjAsField = ObjAsField->GetOwnerStruct(); } if (ObjAsField->IsA<UFunction>()) { ObjAsField = ObjAsField->GetOwnerClass(); } IncludeTheHeaderInBody(ObjAsField); } } if ((Object->IsAsset() || Object->IsA<UBlueprintGeneratedClass>()) && !Object->IsIn(CurrentlyConvertedStruct)) { return; } auto OwnedByAnythingInHierarchy = [&]()->bool { for (UStruct* IterStruct = CurrentlyConvertedStruct; IterStruct; IterStruct = IterStruct->GetSuperStruct()) { if (Object->IsIn(IterStruct)) { return true; } UClass* IterClass = Cast<UClass>(IterStruct); UObject* CDO = IterClass ? IterClass->GetDefaultObject(false) : nullptr; if (CDO && Object->IsIn(CDO)) { return true; } } return false; }; if (!Object->IsA<UField>() && !Object->HasAnyFlags(RF_ClassDefaultObject) && !OwnedByAnythingInHierarchy()) { Object = Object->GetClass(); } FindReferencesForNewObject(Object); }
//------------------------------------------------------------------------------ void FBlueprintActionMenuUtils::MakeContextMenu(FBlueprintActionContext const& Context, bool bIsContextSensitive, FBlueprintActionMenuBuilder& MenuOut) { using namespace BlueprintActionMenuUtilsImpl; //-------------------------------------- // Composing Filters //-------------------------------------- FBlueprintActionFilter MainMenuFilter; MainMenuFilter.Context = Context; MainMenuFilter.Context.SelectedObjects.Empty(); FBlueprintActionFilter ComponentsFilter; ComponentsFilter.Context = Context; // only want bound actions for this menu section ComponentsFilter.AddRejectionTest(FBlueprintActionFilter::FRejectionTestDelegate::CreateStatic(IsUnBoundSpawner)); // @TODO: don't know exactly why we can only bind non-pure/const functions; // this is mirrored after FK2ActionMenuBuilder::GetFunctionCallsOnSelectedActors() // and FK2ActionMenuBuilder::GetFunctionCallsOnSelectedComponents(), // where we make the same stipulation ComponentsFilter.AddRejectionTest(FBlueprintActionFilter::FRejectionTestDelegate::CreateStatic(IsPureNonConstAction)); FBlueprintActionFilter LevelActorsFilter; LevelActorsFilter.Context = Context; // only want bound actions for this menu section LevelActorsFilter.AddRejectionTest(FBlueprintActionFilter::FRejectionTestDelegate::CreateStatic(IsUnBoundSpawner)); const UBlueprintEditorSettings* BlueprintSettings = GetDefault<UBlueprintEditorSettings>(); bool const bAddTargetContext = bIsContextSensitive && BlueprintSettings->bUseTargetContextForNodeMenu; bool bCanOperateOnLevelActors = bIsContextSensitive && (Context.Pins.Num() == 0); bool bCanHaveActorComponents = bIsContextSensitive; // determine if we can operate on certain object selections (level actors, // components, etc.) for (UBlueprint* Blueprint : Context.Blueprints) { UClass* BlueprintClass = Blueprint->SkeletonGeneratedClass; if (BlueprintClass != nullptr) { bCanOperateOnLevelActors &= BlueprintClass->IsChildOf<ALevelScriptActor>(); if (bAddTargetContext) { MainMenuFilter.TargetClasses.Add(BlueprintClass); } } bCanHaveActorComponents &= FBlueprintEditorUtils::DoesSupportComponents(Blueprint); } UEdGraphSchema_K2 const* K2Schema = GetDefault<UEdGraphSchema_K2>(); // make sure the bound menu sections have the proper OwnerClasses specified for (UObject* Selection : Context.SelectedObjects) { if (UObjectProperty* ObjProperty = Cast<UObjectProperty>(Selection)) { LevelActorsFilter.Context.SelectedObjects.Remove(Selection); } else if (AActor* LevelActor = Cast<AActor>(Selection)) { ComponentsFilter.Context.SelectedObjects.Remove(Selection); if (!bCanOperateOnLevelActors || (!LevelActor->NeedsLoadForClient() && !LevelActor->NeedsLoadForServer())) { // don't want to let the level script operate on actors that won't be loaded in game LevelActorsFilter.Context.SelectedObjects.Remove(Selection); } else { // Make sure every blueprint is in the same level as this actor for (UBlueprint* Blueprint : Context.Blueprints) { if (!K2Schema->IsActorValidForLevelScriptRefs(LevelActor, Blueprint)) { LevelActorsFilter.Context.SelectedObjects.Remove(Selection); break; } } } } else { ComponentsFilter.Context.SelectedObjects.Remove(Selection); LevelActorsFilter.Context.SelectedObjects.Remove(Selection); } } // make sure all selected level actors are accounted for (in case the caller // did not include them in the context) for (FSelectionIterator LvlActorIt(*GEditor->GetSelectedActors()); LvlActorIt; ++LvlActorIt) { AActor* LevelActor = Cast<AActor>(*LvlActorIt); // don't want to let the level script operate on actors that won't be loaded in game if (bCanOperateOnLevelActors && (LevelActor->NeedsLoadForClient() || LevelActor->NeedsLoadForServer())) { bool bAddActor = true; // Make sure every blueprint is in the same level as this actor for (UBlueprint* Blueprint : Context.Blueprints) { if (!K2Schema->IsActorValidForLevelScriptRefs(LevelActor, Blueprint)) { bAddActor = false; break; } } if (bAddActor) { LevelActorsFilter.Context.SelectedObjects.AddUnique(LevelActor); } } } if(bCanHaveActorComponents) { // Don't allow actor components in static function graphs UEdGraphSchema_K2 const* K2Schema = GetDefault<UEdGraphSchema_K2>(); for (UEdGraph* Graph : Context.Graphs) { bCanHaveActorComponents &= !K2Schema->IsStaticFunctionGraph(Graph); } } if (bAddTargetContext) { bool bContextPinIsObj = false; // if we're dragging from a pin, we further extend the context to cover // that pin and any other pins it sits beside for (UEdGraphPin* ContextPin : Context.Pins) { // we only want the pin to be the target class when it is an output // (doesn't make sense to get members to plug into their parent) if (ContextPin->Direction == EGPD_Input) { continue; } if (UClass* PinObjClass = GetPinClassType(ContextPin)) { if (!bContextPinIsObj) { MainMenuFilter.TargetClasses.Empty(); } MainMenuFilter.TargetClasses.Add(PinObjClass); bContextPinIsObj = true; } for (UEdGraphPin* NodePin : ContextPin->GetOwningNode()->Pins) { if ((NodePin->Direction == ContextPin->Direction) && !bContextPinIsObj) { if (UClass* PinClass = GetPinClassType(NodePin)) { MainMenuFilter.TargetClasses.Add(PinClass); } } } } } // should be called AFTER the MainMenuFilter if fully constructed FBlueprintActionFilter CallOnMemberFilter = MakeCallOnMemberFilter(MainMenuFilter); FBlueprintActionFilter AddComponentFilter; AddComponentFilter.Context = MainMenuFilter.Context; AddComponentFilter.PermittedNodeTypes.Add(UK2Node_AddComponent::StaticClass()); AddComponentFilter.AddRejectionTest(FBlueprintActionFilter::FRejectionTestDelegate::CreateStatic(IsUnBoundSpawner)); for (FSelectionIterator SelectionIt(*GEditor->GetSelectedObjects()); SelectionIt; ++SelectionIt) { UObject* PerspectiveAsset = *SelectionIt; if (PerspectiveAsset->IsAsset()) { AddComponentFilter.Context.SelectedObjects.Add(PerspectiveAsset); } } //-------------------------------------- // Defining Menu Sections //-------------------------------------- MenuOut.Empty(); if (!bIsContextSensitive) { MainMenuFilter.Context.Pins.Empty(); } // for legacy purposes, we have to add the main menu section first (when // reconstructing the legacy menu, we pull the first menu system) MenuOut.AddMenuSection(MainMenuFilter, FText::GetEmpty(), MainMenuSectionGroup); bool const bAddComponentsSection = bIsContextSensitive && bCanHaveActorComponents && (ComponentsFilter.Context.SelectedObjects.Num() > 0); // add the components section to the menu (if we don't have any components // selected, then inform the user through a dummy menu entry) if (bAddComponentsSection) { AddComponentSections(ComponentsFilter, MenuOut); } bool const bAddLevelActorsSection = bIsContextSensitive && bCanOperateOnLevelActors && (LevelActorsFilter.Context.SelectedObjects.Num() > 0); // add the level actor section to the menu if (bAddLevelActorsSection) { AddLevelActorSections(LevelActorsFilter, MenuOut); } if (bIsContextSensitive) { AddFavoritesSection(MainMenuFilter, MenuOut); MenuOut.AddMenuSection(CallOnMemberFilter, FText::GetEmpty(), MainMenuSectionGroup); MenuOut.AddMenuSection(AddComponentFilter, FText::GetEmpty(), BoundAddComponentGroup); } //-------------------------------------- // Building the Menu //-------------------------------------- MenuOut.RebuildActionList(); if (!BlueprintSettings->bForceLegacyMenuingSystem) { for (UEdGraph const* Graph : Context.Graphs) { if (FKismetEditorUtilities::CanPasteNodes(Graph)) { // @TODO: Grey out menu option with tooltip if one of the nodes cannot paste into this graph TSharedPtr<FEdGraphSchemaAction> PasteHereAction(new FEdGraphSchemaAction_K2PasteHere(TEXT(""), LOCTEXT("PasteHereMenuName", "Paste here"), TEXT(""), MainMenuSectionGroup)); MenuOut.AddAction(PasteHereAction); break; } } if (bIsContextSensitive && bCanHaveActorComponents && !bAddComponentsSection) { FText SelectComponentMsg = LOCTEXT("SelectComponentForEvents", "Select a Component to see available Events & Functions"); FText SelectComponentToolTip = LOCTEXT("SelectComponentForEventsTooltip", "Select a Component in the MyBlueprint tab to see available Events and Functions in this menu."); TSharedPtr<FEdGraphSchemaAction> MsgAction = TSharedPtr<FEdGraphSchemaAction>(new FEdGraphSchemaAction_Dummy(TEXT(""), SelectComponentMsg, SelectComponentToolTip.ToString(), ComponentsSectionGroup)); MenuOut.AddAction(MsgAction); } if (bIsContextSensitive && bCanOperateOnLevelActors && !bAddLevelActorsSection) { FText SelectActorsMsg = LOCTEXT("SelectActorForEvents", "Select Actor(s) to see available Events & Functions"); FText SelectActorsToolTip = LOCTEXT("SelectActorForEventsTooltip", "Select Actor(s) in the level to see available Events and Functions in this menu."); TSharedPtr<FEdGraphSchemaAction> MsgAction = TSharedPtr<FEdGraphSchemaAction>(new FEdGraphSchemaAction_Dummy(TEXT(""), SelectActorsMsg, SelectActorsToolTip.ToString(), LevelActorSectionGroup)); MenuOut.AddAction(MsgAction); } } }