#pragma once #include "CoreMinimal.h" #include "WingBasics.h" #include "WingServer.h" #include "WingFetcher.h" #include "WingProperty.h" #include "WingUtils.h" #include "EdGraph/EdGraphPin.h" #include "EdGraphSchema_K2.h" #include "MaterialGraph/MaterialGraphSchema.h" #include "GraphNode_SetDefaults.generated.h" // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- USTRUCT() struct FSetNodeDefaultEntry { GENERATED_BODY() UPROPERTY() FString Node; UPROPERTY() FString Name; UPROPERTY() FString Value; }; UCLASS() class UWing_GraphNode_SetDefaults : public UWingHandler { GENERATED_BODY() public: UPROPERTY(EditAnywhere, meta=(Description="Target graph")) FString Graph; UPROPERTY(EditAnywhere, meta=(Description="Array of {node, name, value} objects")) FWingJsonArray Pins; virtual void Register() override { UWingServer::AddHandler(this, TEXT("Set the default value of input pins or material expression properties on nodes.")); } // ----------------------------------------------------------------------- // K2 graphs: set pin default values. // ----------------------------------------------------------------------- void HandleK2Entry(const FSetNodeDefaultEntry& Entry, UEdGraph* GraphObj, const UEdGraphSchema_K2* K2Schema) { WingFetcher F(GraphObj, WingOut::Stdout); UWingGraphPinRef* PinRef = F.Node(Entry.Node).Pin(Entry.Name).Cast(); if (!PinRef) return; UEdGraphPin* Pin = WingUtils::CheckGetPin(PinRef->Node, PinRef->PinName, WingOut::Stdout); if (!Pin) return; UEdGraphNode* Node = Pin->GetOwningNode(); if (Pin->Direction != EGPD_Input) { WingOut::Stdout.Printf(TEXT("error: %s is an output pin\n"), *WingUtils::FormatName(Pin)); return; } FString UseDefaultValue; TObjectPtr UseDefaultObject = nullptr; FText UseDefaultText; K2Schema->GetPinDefaultValuesFromString(Pin->PinType, Node, Entry.Value, UseDefaultValue, UseDefaultObject, UseDefaultText, false); FString Error = K2Schema->IsPinDefaultValid(Pin, UseDefaultValue, UseDefaultObject, UseDefaultText); if (!Error.IsEmpty()) { WingOut::Stdout.Printf(TEXT("error: %s: %s\n"), *WingUtils::FormatName(Pin), *Error); return; } UWingServer::AddTouchedObject(Node); K2Schema->TrySetDefaultValue(*Pin, Entry.Value); } // ----------------------------------------------------------------------- // Material graphs: set material expression properties. // ----------------------------------------------------------------------- void HandleMaterialEntry(const FSetNodeDefaultEntry& Entry, UEdGraph* GraphObj) { WingFetcher F(GraphObj, WingOut::Stdout); UEdGraphNode* Node = F.Node(Entry.Node).Cast(); if (!Node) return; TArray All = FWingProperty::GetDetails(Node, true); FWingProperty *P = WingUtils::FindOneWithExternalID(Entry.Name, All, TEXT("Property"), WingOut::Stdout); if (!P) return; UWingServer::AddTouchedObject(Node); if (!P->SetText(Entry.Value, WingOut::Stdout)) return; } // ----------------------------------------------------------------------- virtual void Handle() override { // Fetch the graph once. WingFetcher GraphFetcher(WingOut::Stdout); UEdGraph* GraphObj = GraphFetcher.Walk(Graph).Cast(); if (!GraphObj) return; const UEdGraphSchema* Schema = GraphObj->GetSchema(); const UEdGraphSchema_K2* K2Schema = Cast(Schema); const UMaterialGraphSchema* MGSchema = Cast(Schema); if (!K2Schema && !MGSchema) { WingOut::Stdout.Printf(TEXT("error: unsupported graph schema %s\n"), *Schema->GetClass()->GetName()); return; } FSetNodeDefaultEntry Entry; TArray Props = FWingProperty::GetAll(nullptr, &Entry, FSetNodeDefaultEntry::StaticStruct(), true); for (const TSharedPtr& PinVal : Pins.Array) { if (!FWingProperty::PopulateFromJson(Props, *PinVal, false, WingOut::Stdout)) continue; if (K2Schema) HandleK2Entry(Entry, GraphObj, K2Schema); else if (MGSchema) HandleMaterialEntry(Entry, GraphObj); } WingOut::Stdout.Printf(TEXT("Done.\n")); } };