G6a : FindCenterOfPolygon rebranché dans GI, commandlet LPFixFindCenter
Phase G6a (CHG-115). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
b8414af456
commit
7b5e1a5179
3 changed files with 275 additions and 0 deletions
Binary file not shown.
255
Source/LifePlayEditorTools/LPFixFindCenterCommandlet.cpp
Normal file
255
Source/LifePlayEditorTools/LPFixFindCenterCommandlet.cpp
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
#include "LPFixFindCenterCommandlet.h"
|
||||
|
||||
#include "AssetRegistry/AssetRegistryModule.h"
|
||||
#include "EdGraph/EdGraph.h"
|
||||
#include "EdGraphSchema_K2.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "K2Node_CallFunction.h"
|
||||
#include "Kismet2/BlueprintEditorUtils.h"
|
||||
#include "Kismet2/KismetEditorUtilities.h"
|
||||
#include "LPDataCompat.h"
|
||||
#include "Misc/PackageName.h"
|
||||
#include "UObject/SavePackage.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY_STATIC(LogLPFixFindCenter, Log, All);
|
||||
|
||||
namespace
|
||||
{
|
||||
// EventGraph : ville, extension, troisieme boucle de batiments. MoveTo : meme fonction hors chargement.
|
||||
constexpr int32 ExpectedCalls = 4;
|
||||
|
||||
TArray<FString> Links(const UEdGraphPin* Pin)
|
||||
{
|
||||
TArray<FString> Out;
|
||||
if (Pin)
|
||||
{
|
||||
for (const UEdGraphPin* L : Pin->LinkedTo)
|
||||
{
|
||||
Out.Add(FString::Printf(TEXT("%s.%s"),
|
||||
L && L->GetOwningNode() ? *L->GetOwningNode()->GetName() : TEXT("?"),
|
||||
L ? *L->PinName.ToString() : TEXT("?")));
|
||||
}
|
||||
}
|
||||
Out.Sort();
|
||||
return Out;
|
||||
}
|
||||
|
||||
FString PinState(const UEdGraphPin* Pin)
|
||||
{
|
||||
return FString::Printf(TEXT("[%s] defaut='%s'"),
|
||||
*FString::Join(Links(Pin), TEXT(", ")), *Pin->DefaultValue);
|
||||
}
|
||||
|
||||
bool IsTargetPin(const UEdGraphPin* Pin)
|
||||
{
|
||||
return Pin && (Pin->PinName == UEdGraphSchema_K2::PN_Self || Pin->PinName == FName(TEXT("Target")));
|
||||
}
|
||||
|
||||
UFunction* ReplacementFor(const UK2Node_CallFunction* Node)
|
||||
{
|
||||
if (!Node || Node->FunctionReference.GetMemberName() != FName(TEXT("FindCenterOfPolygon")))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
const UClass* Owner = Node->FunctionReference.GetMemberParentClass(Node->GetBlueprintClassFromNode());
|
||||
if (!Owner || (!Owner->GetName().StartsWith(TEXT("GI_C")) && !Owner->GetName().StartsWith(TEXT("SKEL_GI_C"))))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return ULPDataCompat::StaticClass()->FindFunctionByName(TEXT("FindCenterOfPolygon"));
|
||||
}
|
||||
}
|
||||
|
||||
ULPFixFindCenterCommandlet::ULPFixFindCenterCommandlet()
|
||||
{
|
||||
IsClient = false;
|
||||
IsServer = false;
|
||||
IsEditor = true;
|
||||
LogToConsole = true;
|
||||
}
|
||||
|
||||
int32 ULPFixFindCenterCommandlet::Main(const FString& Params)
|
||||
{
|
||||
const bool bDryRun = Params.Contains(TEXT("DryRun"), ESearchCase::IgnoreCase);
|
||||
if (!ULPDataCompat::StaticClass()->FindFunctionByName(TEXT("FindCenterOfPolygon")))
|
||||
{
|
||||
UE_LOG(LogLPFixFindCenter, Error, TEXT("ULPDataCompat::FindCenterOfPolygon introuvable."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
UE_LOG(LogLPFixFindCenter, Warning, TEXT("=== GI::FindCenterOfPolygon -> LPDataCompat%s ==="),
|
||||
bDryRun ? TEXT(" [DRY RUN]") : TEXT(""));
|
||||
|
||||
FAssetRegistryModule& AssetRegistryModule =
|
||||
FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
|
||||
AssetRegistryModule.Get().SearchAllAssets(true);
|
||||
|
||||
TArray<FAssetData> BlueprintAssets;
|
||||
AssetRegistryModule.Get().GetAssetsByClass(UBlueprint::StaticClass()->GetClassPathName(), BlueprintAssets, true);
|
||||
const UEdGraphSchema_K2* Schema = GetDefault<UEdGraphSchema_K2>();
|
||||
|
||||
int32 NodesFound = 0;
|
||||
int32 NodesFixed = 0;
|
||||
UBlueprint* GI = nullptr;
|
||||
|
||||
for (const FAssetData& AssetData : BlueprintAssets)
|
||||
{
|
||||
if (AssetData.PackageName != FName(TEXT("/Game/BPs/GI")))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
GI = Cast<UBlueprint>(AssetData.GetAsset());
|
||||
break;
|
||||
}
|
||||
if (!GI)
|
||||
{
|
||||
UE_LOG(LogLPFixFindCenter, Error, TEXT("Blueprint /Game/BPs/GI introuvable."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
TArray<UEdGraph*> Graphs;
|
||||
GI->GetAllGraphs(Graphs);
|
||||
for (UEdGraph* Graph : Graphs)
|
||||
{
|
||||
if (!Graph)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
TArray<UEdGraphNode*> Snapshot = Graph->Nodes;
|
||||
for (UEdGraphNode* GraphNode : Snapshot)
|
||||
{
|
||||
UK2Node_CallFunction* OldNode = Cast<UK2Node_CallFunction>(GraphNode);
|
||||
UFunction* NewFunction = ReplacementFor(OldNode);
|
||||
if (!NewFunction)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
++NodesFound;
|
||||
UE_LOG(LogLPFixFindCenter, Warning, TEXT(" %s %s (%d, %d)"),
|
||||
*Graph->GetName(), *OldNode->GetName(), OldNode->NodePosX, OldNode->NodePosY);
|
||||
|
||||
const UEdGraphPin* OldSelf = OldNode->FindPin(UEdGraphSchema_K2::PN_Self, EGPD_Input);
|
||||
if (OldSelf && OldSelf->LinkedTo.Num() > 0)
|
||||
{
|
||||
UE_LOG(LogLPFixFindCenter, Error, TEXT(" cible self reliee, abandon."));
|
||||
return 1;
|
||||
}
|
||||
if (bDryRun)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
TMap<FName, FString> Before;
|
||||
for (const UEdGraphPin* Pin : OldNode->Pins)
|
||||
{
|
||||
if (Pin && !IsTargetPin(Pin))
|
||||
{
|
||||
Before.Add(Pin->PinName, PinState(Pin));
|
||||
}
|
||||
}
|
||||
|
||||
UK2Node_CallFunction* NewNode = NewObject<UK2Node_CallFunction>(Graph);
|
||||
NewNode->SetFromFunction(NewFunction);
|
||||
NewNode->NodePosX = OldNode->NodePosX;
|
||||
NewNode->NodePosY = OldNode->NodePosY;
|
||||
NewNode->CreateNewGuid();
|
||||
NewNode->PostPlacedNewNode();
|
||||
NewNode->AllocateDefaultPins();
|
||||
Graph->Modify();
|
||||
Graph->AddNode(NewNode, false, false);
|
||||
|
||||
bool bOk = true;
|
||||
for (UEdGraphPin* OldPin : OldNode->Pins)
|
||||
{
|
||||
if (!OldPin || IsTargetPin(OldPin))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
UEdGraphPin* NewPin = NewNode->FindPin(OldPin->PinName, OldPin->Direction);
|
||||
if (!NewPin)
|
||||
{
|
||||
bOk = false;
|
||||
UE_LOG(LogLPFixFindCenter, Error, TEXT(" broche %s sans equivalent."), *OldPin->PinName.ToString());
|
||||
break;
|
||||
}
|
||||
NewPin->DefaultValue = OldPin->DefaultValue;
|
||||
NewPin->DefaultObject = OldPin->DefaultObject;
|
||||
NewPin->DefaultTextValue = OldPin->DefaultTextValue;
|
||||
if (OldPin->LinkedTo.Num() > 0
|
||||
&& Schema->MovePinLinks(*OldPin, *NewPin).Response == CONNECT_RESPONSE_DISALLOW)
|
||||
{
|
||||
bOk = false;
|
||||
UE_LOG(LogLPFixFindCenter, Error, TEXT(" liaison refusee sur %s."), *OldPin->PinName.ToString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bOk)
|
||||
{
|
||||
int32 Compared = 0;
|
||||
for (const UEdGraphPin* NewPin : NewNode->Pins)
|
||||
{
|
||||
if (!NewPin || IsTargetPin(NewPin))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const FString* Expected = Before.Find(NewPin->PinName);
|
||||
if (!Expected || *Expected != PinState(NewPin))
|
||||
{
|
||||
bOk = false;
|
||||
UE_LOG(LogLPFixFindCenter, Error, TEXT(" apres : %s %s (attendu %s)"),
|
||||
*NewPin->PinName.ToString(), *PinState(NewPin), Expected ? **Expected : TEXT("<absent>"));
|
||||
}
|
||||
++Compared;
|
||||
}
|
||||
if (Compared != Before.Num())
|
||||
{
|
||||
bOk = false;
|
||||
UE_LOG(LogLPFixFindCenter, Error, TEXT(" %d broche(s) apres, %d avant."), Compared, Before.Num());
|
||||
}
|
||||
}
|
||||
if (!bOk)
|
||||
{
|
||||
UE_LOG(LogLPFixFindCenter, Error, TEXT(" ecart : Blueprint non sauvegarde."));
|
||||
return 1;
|
||||
}
|
||||
OldNode->DestroyNode();
|
||||
++NodesFixed;
|
||||
}
|
||||
}
|
||||
|
||||
UE_LOG(LogLPFixFindCenter, Warning, TEXT("=== %d appel(s) trouve(s), %d remplace(s), attendu %d ==="),
|
||||
NodesFound, NodesFixed, ExpectedCalls);
|
||||
if (NodesFound != ExpectedCalls || (!bDryRun && NodesFixed != ExpectedCalls))
|
||||
{
|
||||
UE_LOG(LogLPFixFindCenter, Error, TEXT("Compte inattendu : Blueprint non sauvegarde."));
|
||||
return 1;
|
||||
}
|
||||
if (bDryRun)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GI);
|
||||
FKismetEditorUtilities::CompileBlueprint(GI);
|
||||
UPackage* Package = GI->GetOutermost();
|
||||
FString Filename;
|
||||
if (!FPackageName::TryConvertLongPackageNameToFilename(
|
||||
Package->GetName(), Filename, FPackageName::GetAssetPackageExtension()))
|
||||
{
|
||||
UE_LOG(LogLPFixFindCenter, 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(LogLPFixFindCenter, Error, TEXT("ECHEC de sauvegarde"));
|
||||
return 1;
|
||||
}
|
||||
UE_LOG(LogLPFixFindCenter, Warning, TEXT("GI sauvegarde."));
|
||||
return 0;
|
||||
}
|
||||
20
Source/LifePlayEditorTools/LPFixFindCenterCommandlet.h
Normal file
20
Source/LifePlayEditorTools/LPFixFindCenterCommandlet.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Rebranche les appels GI::FindCenterOfPolygon vers ULPDataCompat::FindCenterOfPolygon.
|
||||
// La fonction Blueprint d'origine reste dans GI. Tout ecart de broche : Blueprint non sauvegarde.
|
||||
//
|
||||
// Usage :
|
||||
// UnrealEditor-Cmd.exe <projet> -run=LPFixFindCenter [-DryRun]
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Commandlets/Commandlet.h"
|
||||
#include "LPFixFindCenterCommandlet.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class ULPFixFindCenterCommandlet : public UCommandlet
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
ULPFixFindCenterCommandlet();
|
||||
virtual int32 Main(const FString& Params) override;
|
||||
};
|
||||
Loading…
Reference in a new issue