// Voir LPFixPawnResponseCommandlet.h #include "LPFixPawnResponseCommandlet.h" #include "EdGraph/EdGraph.h" #include "EdGraphSchema_K2.h" #include "Engine/Blueprint.h" #include "Engine/SCS_Node.h" #include "Engine/SimpleConstructionScript.h" #include "K2Node_CallFunction.h" #include "Kismet2/BlueprintEditorUtils.h" #include "Kismet2/KismetEditorUtilities.h" #include "Misc/PackageName.h" #include "UObject/Package.h" #include "UObject/SavePackage.h" DEFINE_LOG_CATEGORY_STATIC(LogLPFixPawn, Log, All); ULPFixPawnResponseCommandlet::ULPFixPawnResponseCommandlet() { IsClient = false; IsServer = false; IsEditor = true; LogToConsole = true; } int32 ULPFixPawnResponseCommandlet::Main(const FString& Params) { const bool bDryRun = Params.Contains(TEXT("DryRun"), ESearchCase::IgnoreCase); UBlueprint* Room = LoadObject(nullptr, TEXT("/Game/BPs/Room.Room")); if (!Room) { UE_LOG(LogLPFixPawn, Error, TEXT("Blueprint Room introuvable")); return 1; } UK2Node_CallFunction* PawnNode = nullptr; UK2Node_CallFunction* TypeNode = nullptr; UK2Node_CallFunction* ScaleNode = nullptr; for (UEdGraph* Graph : Room->FunctionGraphs) { if (!Graph || Graph->GetName() != TEXT("addObject")) { continue; } for (UEdGraphNode* Node : Graph->Nodes) { UK2Node_CallFunction* Call = Cast(Node); if (!Call) { continue; } const FName Function = Call->FunctionReference.GetMemberName(); if (Function == TEXT("SetCollisionResponseToChannel")) { UEdGraphPin* Channel = Call->FindPin(TEXT("Channel")); if (Channel && Channel->DefaultValue == TEXT("ECC_Pawn")) { PawnNode = Call; } } else if (Function == TEXT("SetCollisionObjectType")) { TypeNode = Call; } else if (Function == TEXT("SetWorldScale3D")) { ScaleNode = Call; } } } if (!PawnNode || !TypeNode || !ScaleNode) { UE_LOG(LogLPFixPawn, Error, TEXT("noeuds addObject introuvables : Blueprint non sauvegarde")); return 1; } UEdGraphPin* Response = PawnNode->FindPin(TEXT("NewResponse")); UEdGraphPin* TypeChannel = TypeNode->FindPin(TEXT("Channel")); UEdGraphPin* PawnThen = PawnNode->FindPin(UEdGraphSchema_K2::PN_Then); UEdGraphPin* TypeExec = TypeNode->FindPin(UEdGraphSchema_K2::PN_Execute); UEdGraphPin* TypeThen = TypeNode->FindPin(UEdGraphSchema_K2::PN_Then); UEdGraphPin* ScaleExec = ScaleNode->FindPin(UEdGraphSchema_K2::PN_Execute); if (!Response || !TypeChannel || !PawnThen || !TypeExec || !TypeThen || !ScaleExec) { UE_LOG(LogLPFixPawn, Error, TEXT("broches introuvables : Blueprint non sauvegarde")); return 1; } UE_LOG(LogLPFixPawn, Warning, TEXT("Pawn %s, type %s"), *Response->DefaultValue, *TypeChannel->DefaultValue); const bool bPawnDone = Response->DefaultValue == TEXT("ECR_Block"); const bool bTypeDone = TypeChannel->DefaultValue == TEXT("ECC_WorldDynamic") && TypeExec->LinkedTo.Contains(PawnThen); if (!bPawnDone && Response->DefaultValue != TEXT("ECR_Ignore")) { UE_LOG(LogLPFixPawn, Error, TEXT("reponse Pawn inattendue : Blueprint non sauvegarde")); return 1; } int32 Walls = 0; const TCHAR* WallNames[] = { TEXT("Wall1"), TEXT("Wall2"), TEXT("Wall3"), TEXT("Wall4") }; if (!bDryRun) { if (!bPawnDone) { Response->DefaultValue = TEXT("ECR_Block"); } if (!bTypeDone) { TypeChannel->DefaultValue = TEXT("ECC_WorldDynamic"); PawnThen->BreakLinkTo(ScaleExec); TypeExec->BreakAllPinLinks(); TypeThen->BreakAllPinLinks(); PawnThen->MakeLinkTo(TypeExec); TypeThen->MakeLinkTo(ScaleExec); } if (Room->SimpleConstructionScript) { for (const TCHAR* Name : WallNames) { USCS_Node* Node = Room->SimpleConstructionScript->FindSCSNode(FName(Name)); UPrimitiveComponent* Wall = Node ? Cast(Node->ComponentTemplate) : nullptr; if (!Wall) { UE_LOG(LogLPFixPawn, Error, TEXT("mur %s introuvable"), Name); return 1; } Wall->Modify(); Wall->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); Wall->SetCollisionObjectType(ECC_WorldDynamic); Wall->SetCollisionResponseToChannel(ECC_Pawn, ECR_Block); ++Walls; } } } UE_LOG(LogLPFixPawn, Warning, TEXT("=== addObject Pawn Block, type WorldDynamic, %d murs%s ==="), bDryRun ? 4 : Walls, bDryRun ? TEXT(" [DRY RUN]") : TEXT("")); if (bDryRun) { return 0; } FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(Room); FKismetEditorUtilities::CompileBlueprint(Room); UPackage* Package = Room->GetOutermost(); FString Filename; if (!FPackageName::TryConvertLongPackageNameToFilename(Package->GetName(), Filename, FPackageName::GetAssetPackageExtension())) { UE_LOG(LogLPFixPawn, Error, TEXT("chemin introuvable")); return 1; } ResetLoaders(Package); FSavePackageArgs SaveArgs; SaveArgs.TopLevelFlags = RF_Public | RF_Standalone; SaveArgs.SaveFlags = SAVE_None; SaveArgs.bWarnOfLongFilename = true; SaveArgs.Error = GWarn; if (!UPackage::SavePackage(Package, nullptr, *Filename, SaveArgs)) { UE_LOG(LogLPFixPawn, Error, TEXT("sauvegarde echouee")); return 1; } UE_LOG(LogLPFixPawn, Warning, TEXT("Room sauvegarde : meubles et murs en WorldDynamic, Pawn Block")); return 0; }