Enormouse overhaul
This commit is contained in:
@@ -45,16 +45,16 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UBlueprint* BP = F.Asset(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
// Check that the proposed name is valid
|
||||
FName InternalID = WingUtils::CheckProposedName(Component);
|
||||
FName InternalID = WingUtils::CheckProposedName(Component, WingOut::Stdout);
|
||||
if (InternalID.IsNone()) return;
|
||||
TSet<FName> Names;
|
||||
FBlueprintEditorUtils::GetClassVariableList(BP, Names);
|
||||
if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("variable or component"))) return;
|
||||
if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("variable or component"), WingOut::Stdout)) return;
|
||||
|
||||
// Resolve the component class by name
|
||||
UWingTypes::Requirements Req;
|
||||
@@ -62,18 +62,18 @@ public:
|
||||
Req.Blueprintable = false;
|
||||
Req.AllowContainer = false;
|
||||
Req.IsChildOf = UActorComponent::StaticClass();
|
||||
UClass* ComponentClass = UWingTypes::TextToOneObjectType(Class, Req);
|
||||
UClass* ComponentClass = UWingTypes::TextToOneObjectType(Class, Req, WingOut::Stdout);
|
||||
if (!ComponentClass) return;
|
||||
if (!UWingComponentReference::CheckValidComponentClass(ComponentClass)) return;
|
||||
if (!UWingComponentReference::CheckValidComponentClass(ComponentClass, WingOut::Stdout)) return;
|
||||
|
||||
// Find the specified parent component
|
||||
TArray<UWingComponentReference*> AllComponents = UWingComponentReference::GetAll(BP);
|
||||
UWingComponentReference* ParentComp = WingUtils::FindOneWithExternalID(Parent, AllComponents, TEXT("Component"));
|
||||
UWingComponentReference* ParentComp = WingUtils::FindOneWithExternalID(Parent, AllComponents, TEXT("Component"), WingOut::Stdout);
|
||||
if (!ParentComp) return;
|
||||
|
||||
// Create the SCS node
|
||||
if (!UWingComponentReference::AddComponent(BP, ComponentClass, ParentComp, InternalID)) return;
|
||||
if (!UWingComponentReference::AddComponent(BP, ComponentClass, ParentComp, InternalID, WingOut::Stdout)) return;
|
||||
|
||||
UWingServer::Printf(TEXT("Component Added.\n"));
|
||||
WingOut::Stdout.Printf(TEXT("Component Added.\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -28,12 +28,12 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UWingComponentReference* CompRef = F.Walk(Component).Cast<UWingComponentReference>();
|
||||
if (!CompRef) return;
|
||||
|
||||
if (!CompRef->DeleteComponent()) return;
|
||||
if (!CompRef->DeleteComponent(WingOut::Stdout)) return;
|
||||
|
||||
UWingServer::Printf(TEXT("Removed component.\n"));
|
||||
WingOut::Stdout.Printf(TEXT("Removed component.\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,18 +35,18 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UWingComponentReference* CompRef = F.Walk(Component).Cast<UWingComponentReference>();
|
||||
if (!CompRef) return;
|
||||
|
||||
// Find the new parent among all components (if specified)
|
||||
UBlueprint *BP = CompRef->BP;
|
||||
TArray<UWingComponentReference*> AllComponents = UWingComponentReference::GetAll(BP);
|
||||
UWingComponentReference* NewParent = WingUtils::FindOneWithExternalID(Parent, AllComponents, TEXT("Component"));
|
||||
UWingComponentReference* NewParent = WingUtils::FindOneWithExternalID(Parent, AllComponents, TEXT("Component"), WingOut::Stdout);
|
||||
if (!NewParent) return;
|
||||
|
||||
if (!CompRef->ReparentComponent(NewParent)) return;
|
||||
if (!CompRef->ReparentComponent(NewParent, WingOut::Stdout)) return;
|
||||
|
||||
UWingServer::Printf(TEXT("Reparented component."));
|
||||
WingOut::Stdout.Printf(TEXT("Reparented component."));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
|
||||
if (!IFileManager::Get().FileExists(*Filename))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Asset file not found: %s\n"), *Filename);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Asset file not found: %s\n"), *Filename);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -43,10 +43,10 @@ public:
|
||||
uint32 CopyResult = IFileManager::Get().Copy(*BackupFilename, *Filename, true);
|
||||
if (CopyResult != COPY_OK)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to copy %s to %s\n"), *Filename, *BackupFilename);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Failed to copy %s to %s\n"), *Filename, *BackupFilename);
|
||||
return;
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Backed up to %s\n"), *BackupFilename);
|
||||
WingOut::Stdout.Printf(TEXT("Backed up to %s\n"), *BackupFilename);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -93,11 +93,11 @@ public:
|
||||
}
|
||||
|
||||
Results.Sort();
|
||||
for (const FString &Result : Results) UWingServer::Print(Result);
|
||||
for (const FString &Result : Results) WingOut::Stdout.Print(Result);
|
||||
|
||||
if (Results.IsEmpty())
|
||||
{
|
||||
UWingServer::Printf(TEXT("No contents found at '%s'.\n"), *Path);
|
||||
WingOut::Stdout.Printf(TEXT("No contents found at '%s'.\n"), *Path);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
if (!IFileManager::Get().FileExists(*PackageFilename))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Asset file not found on disk: %s\n"), *PackageFilename);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Asset file not found on disk: %s\n"), *PackageFilename);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -60,22 +60,22 @@ public:
|
||||
|
||||
if (Referencers.Num() > 0 && !Force)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Asset is still referenced by %d package(s):\n"), Referencers.Num());
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Asset is still referenced by %d package(s):\n"), Referencers.Num());
|
||||
for (const FName& Ref : Referencers)
|
||||
{
|
||||
FString RefStr = Ref.ToString();
|
||||
UPackage* RefPackage = FindPackage(nullptr, *RefStr);
|
||||
UWingServer::Printf(TEXT(" %s%s\n"), *RefStr,
|
||||
WingOut::Stdout.Printf(TEXT(" %s%s\n"), *RefStr,
|
||||
RefPackage ? TEXT(" (loaded)") : TEXT(" (on-disk only)"));
|
||||
}
|
||||
UWingServer::Print(TEXT("Use force=true to skip the reference check.\n"));
|
||||
WingOut::Stdout.Print(TEXT("Use force=true to skip the reference check.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Force delete: unload the package from memory first
|
||||
if (Force && Referencers.Num() > 0)
|
||||
{
|
||||
UWingServer::Printf(TEXT("WARNING: Force-deleting despite %d referencer(s).\n"), Referencers.Num());
|
||||
WingOut::Stdout.Printf(TEXT("WARNING: Force-deleting despite %d referencer(s).\n"), Referencers.Num());
|
||||
}
|
||||
|
||||
// Mark the package, and all the objects in it, as NOT
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
|
||||
if (!bDeleted)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to delete file from disk: %s\n"), *PackageFilename);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Failed to delete file from disk: %s\n"), *PackageFilename);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -122,6 +122,6 @@ public:
|
||||
Registry.ScanPathsSynchronous({PackageDir}, true);
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Deleted %s\n"), *Asset);
|
||||
WingOut::Stdout.Printf(TEXT("Deleted %s\n"), *Asset);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
FAssetData AssetData = Registry.GetAssetByObjectPath(FSoftObjectPath(Asset));
|
||||
if (!AssetData.IsValid())
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Asset not found: %s\n"), *Asset);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Asset not found: %s\n"), *Asset);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
if (Referencers.Num() == 0)
|
||||
{
|
||||
UWingServer::Print(TEXT("No referencers found.\n"));
|
||||
WingOut::Stdout.Print(TEXT("No referencers found.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -56,13 +56,13 @@ public:
|
||||
Registry.GetAssetsByPackageName(Ref, RefAssets);
|
||||
if (RefAssets.Num() > 0)
|
||||
{
|
||||
UWingServer::Printf(TEXT("%s %s\n"),
|
||||
WingOut::Stdout.Printf(TEXT("%s %s\n"),
|
||||
*WingUtils::FormatName(RefAssets[0].GetClass()),
|
||||
*RefStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
UWingServer::Printf(TEXT("Unknown %s\n"), *RefStr);
|
||||
WingOut::Stdout.Printf(TEXT("Unknown %s\n"), *RefStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
virtual void Handle() override
|
||||
{
|
||||
// Load the asset
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UObject* AssetObj = F.Asset(Asset).GetObj();
|
||||
if (!AssetObj) return;
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
NewAssetName = NewPath;
|
||||
if (NewPackagePath.IsEmpty())
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Cannot determine directory from Asset '%s'\n"), *Asset);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Cannot determine directory from Asset '%s'\n"), *Asset);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -62,10 +62,10 @@ public:
|
||||
|
||||
if (!AssetTools.RenameAssets(RenameData))
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Rename failed. The target path may be invalid or a conflicting asset may exist.\n"));
|
||||
WingOut::Stdout.Print(TEXT("ERROR: Rename failed. The target path may be invalid or a conflicting asset may exist.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Renamed to %s/%s\n"), *NewPackagePath, *NewAssetName);
|
||||
WingOut::Stdout.Printf(TEXT("Renamed to %s/%s\n"), *NewPackagePath, *NewAssetName);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
|
||||
if (!IFileManager::Get().FileExists(*BackupFilename))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Backup file not found: %s\n"), *BackupFilename);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Backup file not found: %s\n"), *BackupFilename);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
uint32 CopyResult = IFileManager::Get().Copy(*Filename, *BackupFilename, true);
|
||||
if (CopyResult != COPY_OK)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to copy backup over %s\n"), *Asset);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Failed to copy backup over %s\n"), *Asset);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -64,12 +64,12 @@ public:
|
||||
UEditorLoadingAndSavingUtils::ReloadPackages({Package}, bReloaded, ErrorMessage, EReloadPackagesInteractionMode::AssumePositive);
|
||||
if (!bReloaded)
|
||||
{
|
||||
UWingServer::Printf(TEXT("WARNING: Restored %s but reload failed: %s\n"),
|
||||
WingOut::Stdout.Printf(TEXT("WARNING: Restored %s but reload failed: %s\n"),
|
||||
*Asset, *ErrorMessage.ToString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Restored %s from backup\n"), *Asset);
|
||||
WingOut::Stdout.Printf(TEXT("Restored %s from backup\n"), *Asset);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
{
|
||||
if (Query.IsEmpty() && Type.IsEmpty())
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: At least one of Query or Type must be specified\n"));
|
||||
WingOut::Stdout.Print(TEXT("ERROR: At least one of Query or Type must be specified\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
Req.BlueprintType = false;
|
||||
Req.Blueprintable = false;
|
||||
Req.AllowContainer = false;
|
||||
UClass* TypeClass = UWingTypes::TextToOneObjectType(Type, Req);
|
||||
UClass* TypeClass = UWingTypes::TextToOneObjectType(Type, Req, WingOut::Stdout);
|
||||
if (!TypeClass) return;
|
||||
Filter.ClassPaths.Add(TypeClass->GetClassPathName());
|
||||
}
|
||||
@@ -81,18 +81,18 @@ public:
|
||||
|
||||
for (const FAssetData& Data : Results)
|
||||
{
|
||||
UWingServer::Printf(TEXT("%s %s\n"),
|
||||
WingOut::Stdout.Printf(TEXT("%s %s\n"),
|
||||
*WingUtils::FormatName(Data.GetClass()),
|
||||
*Data.PackageName.ToString());
|
||||
}
|
||||
|
||||
if (Results.Num() == 0)
|
||||
{
|
||||
UWingServer::Print(TEXT("No assets found.\n"));
|
||||
WingOut::Stdout.Print(TEXT("No assets found.\n"));
|
||||
}
|
||||
else if (Results.Num() >= Limit)
|
||||
{
|
||||
UWingServer::Printf(TEXT("WARNING: You reached the limit of %d, to raise it, specify the Limit parameter.\n"), Limit);
|
||||
WingOut::Stdout.Printf(TEXT("WARNING: You reached the limit of %d, to raise it, specify the Limit parameter.\n"), Limit);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -47,48 +47,48 @@ public:
|
||||
{
|
||||
if (GraphType != TEXT("function") && GraphType != TEXT("macro"))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Invalid GraphType '%s'. Valid values: function, macro\n"), *GraphType);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Invalid GraphType '%s'. Valid values: function, macro\n"), *GraphType);
|
||||
return;
|
||||
}
|
||||
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
// Check that this graph type is valid for this blueprint type
|
||||
if (BP->BlueprintType == BPTYPE_Interface)
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Cannot add graphs to interface blueprints.\n"));
|
||||
WingOut::Stdout.Print(TEXT("ERROR: Cannot add graphs to interface blueprints.\n"));
|
||||
return;
|
||||
}
|
||||
if (BP->BlueprintType == BPTYPE_MacroLibrary && GraphType == TEXT("function"))
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Macro libraries cannot contain functions.\n"));
|
||||
WingOut::Stdout.Print(TEXT("ERROR: Macro libraries cannot contain functions.\n"));
|
||||
return;
|
||||
}
|
||||
if (BP->BlueprintType == BPTYPE_FunctionLibrary && GraphType == TEXT("macro"))
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Function libraries cannot contain macros.\n"));
|
||||
WingOut::Stdout.Print(TEXT("ERROR: Function libraries cannot contain macros.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check graph name uniqueness and legality
|
||||
FName InternalID = WingUtils::CheckProposedName(Graph);
|
||||
FName InternalID = WingUtils::CheckProposedName(Graph, WingOut::Stdout);
|
||||
if (InternalID.IsNone()) return;
|
||||
if (!WingUtils::FindNoneWithInternalID(InternalID, WingUtils::AllGraphs(BP), TEXT("Graph")))
|
||||
if (!WingUtils::FindNoneWithInternalID(InternalID, WingUtils::AllGraphs(BP), TEXT("Graph"), WingOut::Stdout))
|
||||
return;
|
||||
|
||||
// Parse and validate variables before making changes
|
||||
WingVariables Vars;
|
||||
if (!Vars.InputVariables.ParseString(InputVariables)) return;
|
||||
if (!Vars.OutputVariables.ParseString(OutputVariables)) return;
|
||||
if (!Vars.InputVariables.ParseString(InputVariables, WingOut::Stdout)) return;
|
||||
if (!Vars.OutputVariables.ParseString(OutputVariables, WingOut::Stdout)) return;
|
||||
|
||||
// Create the Graph
|
||||
UEdGraph* NewGraph = FBlueprintEditorUtils::CreateNewGraph(BP, InternalID,
|
||||
UEdGraph::StaticClass(), UEdGraphSchema_K2::StaticClass());
|
||||
if (!NewGraph)
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Failed to create graph\n"));
|
||||
WingOut::Stdout.Print(TEXT("ERROR: Failed to create graph\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -103,10 +103,10 @@ public:
|
||||
}
|
||||
|
||||
// Create the variables on the new graph
|
||||
if (!Vars.SetBackingStore(NewGraph)) return;
|
||||
if (!Vars.Check()) return;
|
||||
if (!Vars.Create()) return;
|
||||
if (!Vars.SetBackingStore(NewGraph, WingOut::Stdout)) return;
|
||||
if (!Vars.Check(WingOut::Stdout)) return;
|
||||
if (!Vars.Create(WingOut::Stdout)) return;
|
||||
|
||||
UWingServer::Printf(TEXT("Created %s graph: %s\n"), *GraphType, *WingUtils::FormatName(NewGraph));
|
||||
WingOut::Stdout.Printf(TEXT("Created %s graph: %s\n"), *GraphType, *WingUtils::FormatName(NewGraph));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -31,25 +31,25 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UEdGraph* FoundGraph = F.Walk(Graph).Cast<UEdGraph>();
|
||||
if (!FoundGraph) return;
|
||||
|
||||
UBlueprint* BP = FBlueprintEditorUtils::FindBlueprintForGraph(FoundGraph);
|
||||
if (!BP)
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Could not find owning blueprint for this graph.\n"));
|
||||
WingOut::Stdout.Print(TEXT("ERROR: Could not find owning blueprint for this graph.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!BP->FunctionGraphs.Contains(FoundGraph) && !BP->MacroGraphs.Contains(FoundGraph))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: %s is not a function or macro graph.\n"), *WingUtils::FormatName(FoundGraph));
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: %s is not a function or macro graph.\n"), *WingUtils::FormatName(FoundGraph));
|
||||
return;
|
||||
}
|
||||
|
||||
FBlueprintEditorUtils::RemoveGraph(BP, FoundGraph, EGraphRemoveFlags::Recompile);
|
||||
|
||||
UWingServer::Printf(TEXT("Deleted graph from %s\n"), *WingUtils::FormatName(BP));
|
||||
WingOut::Stdout.Printf(TEXT("Deleted graph from %s\n"), *WingUtils::FormatName(BP));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UBlueprint* BP = F.Asset(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
Req.BlueprintType = false;
|
||||
Req.Blueprintable = false;
|
||||
Req.AllowContainer = false;
|
||||
UClass* InterfaceClass = UWingTypes::TextToOneInterfaceType(Interface, Req);
|
||||
UClass* InterfaceClass = UWingTypes::TextToOneInterfaceType(Interface, Req, WingOut::Stdout);
|
||||
if (!InterfaceClass) return;
|
||||
|
||||
// Check for duplicates
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
{
|
||||
if (IfaceDesc.Interface == InterfaceClass)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Interface '%s' is already implemented by this Blueprint.\n"),
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Interface '%s' is already implemented by this Blueprint.\n"),
|
||||
*WingUtils::FormatName(InterfaceClass));
|
||||
return;
|
||||
}
|
||||
@@ -61,19 +61,19 @@ public:
|
||||
bool bAdded = FBlueprintEditorUtils::ImplementNewInterface(BP, InterfacePath);
|
||||
if (!bAdded)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: ImplementNewInterface failed for '%s'.\n"),
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: ImplementNewInterface failed for '%s'.\n"),
|
||||
*WingUtils::FormatName(InterfaceClass));
|
||||
return;
|
||||
}
|
||||
|
||||
// Collect stub function graph names from the newly added interface entry
|
||||
UWingServer::Printf(TEXT("Added interface %s\n"), *WingUtils::FormatName(InterfaceClass));
|
||||
WingOut::Stdout.Printf(TEXT("Added interface %s\n"), *WingUtils::FormatName(InterfaceClass));
|
||||
for (const FBPInterfaceDescription& IfaceDesc : BP->ImplementedInterfaces)
|
||||
{
|
||||
if (IfaceDesc.Interface != InterfaceClass) continue;
|
||||
for (const UEdGraph* Graph : IfaceDesc.Graphs)
|
||||
{
|
||||
UWingServer::Printf(TEXT("New Graph: %s\n"), *WingUtils::FormatName(Graph));
|
||||
WingOut::Stdout.Printf(TEXT("New Graph: %s\n"), *WingUtils::FormatName(Graph));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UBlueprint* BP = F.Asset(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
Req.BlueprintType = false;
|
||||
Req.Blueprintable = false;
|
||||
Req.AllowContainer = false;
|
||||
UClass* FoundInterface = UWingTypes::TextToOneInterfaceType(Interface, Req);
|
||||
UClass* FoundInterface = UWingTypes::TextToOneInterfaceType(Interface, Req, WingOut::Stdout);
|
||||
if (!FoundInterface) return;
|
||||
|
||||
// Verify this blueprint actually implements it
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
}
|
||||
if (!Found)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Blueprint %s does not implement interface %s\n"),
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Blueprint %s does not implement interface %s\n"),
|
||||
*WingUtils::FormatName(BP), *WingUtils::FormatName(FoundInterface));
|
||||
return;
|
||||
}
|
||||
@@ -66,8 +66,8 @@ public:
|
||||
FTopLevelAssetPath InterfacePath = FoundInterface->GetClassPathName();
|
||||
FBlueprintEditorUtils::RemoveInterface(BP, InterfacePath, PreserveFunctions);
|
||||
|
||||
UWingServer::Printf(TEXT("Removed interface %s\n"), *WingUtils::FormatName(FoundInterface));
|
||||
WingOut::Stdout.Printf(TEXT("Removed interface %s\n"), *WingUtils::FormatName(FoundInterface));
|
||||
if (PreserveFunctions)
|
||||
UWingServer::Print(TEXT("Function graphs preserved as regular functions.\n"));
|
||||
WingOut::Stdout.Print(TEXT("Function graphs preserved as regular functions.\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UBlueprint* BP = F.Asset(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
@@ -48,11 +48,11 @@ public:
|
||||
{
|
||||
if (!Node->bHasCompilerMessage) continue;
|
||||
const TCHAR* Prefix = (Node->ErrorType == EMessageSeverity::Error) ? TEXT("ERROR") : TEXT("WARNING");
|
||||
UWingServer::Printf(TEXT("%s: [%s] %s: %s\n"),
|
||||
WingOut::Stdout.Printf(TEXT("%s: [%s] %s: %s\n"),
|
||||
Prefix, *WingUtils::FormatName(Node->GetGraph()),
|
||||
*WingUtils::FormatName(Node), *Node->ErrorMsg);
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Compilation Done.\n"));
|
||||
WingOut::Stdout.Printf(TEXT("Compilation Done.\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -42,63 +42,63 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
// Header
|
||||
UWingServer::Printf(TEXT("Blueprint: %s\n"), *WingUtils::FormatName(BP));
|
||||
UWingServer::Printf(TEXT("Parent: %s\n"), BP->ParentClass ? *WingUtils::FormatName(BP->ParentClass) : TEXT("None"));
|
||||
UWingServer::Printf(TEXT("Type: %s\n"), *WingUtils::EnumToString(BP->BlueprintType));
|
||||
WingOut::Stdout.Printf(TEXT("Blueprint: %s\n"), *WingUtils::FormatName(BP));
|
||||
WingOut::Stdout.Printf(TEXT("Parent: %s\n"), BP->ParentClass ? *WingUtils::FormatName(BP->ParentClass) : TEXT("None"));
|
||||
WingOut::Stdout.Printf(TEXT("Type: %s\n"), *WingUtils::EnumToString(BP->BlueprintType));
|
||||
|
||||
// Animation Blueprint
|
||||
if (UAnimBlueprint* AnimBP = Cast<UAnimBlueprint>(BP))
|
||||
{
|
||||
if (AnimBP->TargetSkeleton)
|
||||
UWingServer::Printf(TEXT("TargetSkeleton: %s\n"), *AnimBP->TargetSkeleton->GetPathName());
|
||||
WingOut::Stdout.Printf(TEXT("TargetSkeleton: %s\n"), *AnimBP->TargetSkeleton->GetPathName());
|
||||
}
|
||||
|
||||
// Interfaces
|
||||
for (const FBPInterfaceDescription& I : BP->ImplementedInterfaces)
|
||||
{
|
||||
if (I.Interface) UWingServer::Printf(TEXT("Interface: %s\n"), *WingUtils::FormatName(I));
|
||||
if (I.Interface) WingOut::Stdout.Printf(TEXT("Interface: %s\n"), *WingUtils::FormatName(I));
|
||||
}
|
||||
|
||||
// Variables
|
||||
WingVariables BlueprintVars;
|
||||
BlueprintVars.SetBackingStore(BP);
|
||||
BlueprintVars.Load();
|
||||
BlueprintVars.Print(UWingServer::GetPrintBuffer());
|
||||
BlueprintVars.SetBackingStore(BP, WingOut::Stdout);
|
||||
BlueprintVars.Load(WingOut::Stdout);
|
||||
BlueprintVars.Print(WingOut::StdoutBuffer);
|
||||
|
||||
// Components
|
||||
TArray<UWingComponentReference*> Components3 = UWingComponentReference::GetAll(BP);
|
||||
if (!Components3.IsEmpty())
|
||||
{
|
||||
UWingServer::Print(TEXT("\nComponents:\n"));
|
||||
WingOut::Stdout.Print(TEXT("\nComponents:\n"));
|
||||
for (const UWingComponentReference* Ref : Components3)
|
||||
{
|
||||
UWingServer::Printf(TEXT(" %s %s"),
|
||||
WingOut::Stdout.Printf(TEXT(" %s %s"),
|
||||
*Ref->TypeName,
|
||||
*WingUtils::FormatName(Ref));
|
||||
if (!Ref->ParentName.IsEmpty())
|
||||
UWingServer::Printf(TEXT(" [parent: %s]"), *Ref->ParentName);
|
||||
WingOut::Stdout.Printf(TEXT(" [parent: %s]"), *Ref->ParentName);
|
||||
if (Ref->Inherited)
|
||||
UWingServer::Print(TEXT(" [inherited]"));
|
||||
UWingServer::Print(TEXT("\n"));
|
||||
WingOut::Stdout.Print(TEXT(" [inherited]"));
|
||||
WingOut::Stdout.Print(TEXT("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
// Widget Tree
|
||||
if (UWidgetBlueprint* WidgetBP = Cast<UWidgetBlueprint>(BP))
|
||||
{
|
||||
UWingServer::Print(TEXT("\nWidget Tree:\n"));
|
||||
WingOut::Stdout.Print(TEXT("\nWidget Tree:\n"));
|
||||
WingWidgets::PrintWidgetTree(WidgetBP->WidgetTree->RootWidget, 1);
|
||||
}
|
||||
|
||||
// Event Dispatchers
|
||||
if (!BP->DelegateSignatureGraphs.IsEmpty())
|
||||
{
|
||||
UWingServer::Print(TEXT("\nEvent Dispatchers:\n"));
|
||||
WingOut::Stdout.Print(TEXT("\nEvent Dispatchers:\n"));
|
||||
for (UEdGraph* Graph : BP->DelegateSignatureGraphs)
|
||||
PrintEventDispatcher(Graph);
|
||||
}
|
||||
@@ -106,10 +106,10 @@ public:
|
||||
// Graphs
|
||||
TSet<UEdGraph*> Printed;
|
||||
|
||||
UWingServer::Print(TEXT("\nGraphs:\n"));
|
||||
WingOut::Stdout.Print(TEXT("\nGraphs:\n"));
|
||||
for (UEdGraph* Graph : BP->UbergraphPages)
|
||||
{
|
||||
UWingServer::Printf(TEXT(" EventGraph %s\n"), *WingUtils::FormatName(Graph));
|
||||
WingOut::Stdout.Printf(TEXT(" EventGraph %s\n"), *WingUtils::FormatName(Graph));
|
||||
Printed.Add(Graph);
|
||||
}
|
||||
for (UEdGraph* Graph : BP->FunctionGraphs)
|
||||
@@ -147,7 +147,7 @@ public:
|
||||
Printed.Add(Graph);
|
||||
}
|
||||
if (!AnimGraphNames.IsEmpty())
|
||||
UWingServer::Printf(TEXT("\nAnimation Graphs: %s\n"), *AnimGraphNames);
|
||||
WingOut::Stdout.Printf(TEXT("\nAnimation Graphs: %s\n"), *AnimGraphNames);
|
||||
|
||||
FString StateMachineNames;
|
||||
for (UEdGraph* Graph : AllGraphs)
|
||||
@@ -159,13 +159,13 @@ public:
|
||||
Printed.Add(Graph);
|
||||
}
|
||||
if (!StateMachineNames.IsEmpty())
|
||||
UWingServer::Printf(TEXT("\nAnimation State Machines: %s\n"), *StateMachineNames);
|
||||
WingOut::Stdout.Printf(TEXT("\nAnimation State Machines: %s\n"), *StateMachineNames);
|
||||
|
||||
// Catch any graphs we missed.
|
||||
for (UEdGraph* Graph : AllGraphs)
|
||||
{
|
||||
if (Printed.Contains(Graph)) continue;
|
||||
UWingServer::Printf(TEXT("WARNING: unlisted graph: %s (%s)\n"),
|
||||
WingOut::Stdout.Printf(TEXT("WARNING: unlisted graph: %s (%s)\n"),
|
||||
*WingUtils::FormatName(Graph),
|
||||
*WingUtils::FormatName(Graph->GetSchema()->GetClass()));
|
||||
}
|
||||
@@ -175,22 +175,21 @@ private:
|
||||
void PrintEventDispatcher(UEdGraph* Graph)
|
||||
{
|
||||
WingVariables Vars;
|
||||
Vars.SetBackingStore(Graph);
|
||||
Vars.Load();
|
||||
Vars.SetBackingStore(Graph, WingOut::Stdout);
|
||||
Vars.Load(WingOut::Stdout);
|
||||
|
||||
FStringBuilderBase &Out = UWingServer::GetPrintBuffer();
|
||||
Out.Appendf(TEXT(" %s("), *WingUtils::FormatName(Graph));
|
||||
Vars.InputVariables.PrintCompact(Out);
|
||||
Out.Append(TEXT(")\n"));
|
||||
WingOut::Stdout.Printf(TEXT(" %s("), *WingUtils::FormatName(Graph));
|
||||
Vars.InputVariables.PrintCompact(WingOut::Stdout);
|
||||
WingOut::Stdout.Printf(TEXT(")\n"));
|
||||
}
|
||||
|
||||
void PrintGraph(UEdGraph* Graph, const TCHAR* Type, UClass* Interface = nullptr)
|
||||
{
|
||||
WingVariables Vars;
|
||||
Vars.SetBackingStore(Graph);
|
||||
Vars.Load();
|
||||
Vars.SetBackingStore(Graph, WingOut::Stdout);
|
||||
Vars.Load(WingOut::Stdout);
|
||||
|
||||
FStringBuilderBase &Out = UWingServer::GetPrintBuffer();
|
||||
FStringBuilderBase &Out = WingOut::StdoutBuffer;
|
||||
Out.Appendf(TEXT(" %s %s"), Type, *WingUtils::FormatName(Graph));
|
||||
Out.AppendChar('(');
|
||||
Vars.InputVariables.PrintCompact(Out);
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
virtual void Handle() override
|
||||
{
|
||||
// Load Blueprint
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UBlueprint* BP = F.Asset(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
@@ -45,13 +45,13 @@ public:
|
||||
Req.BlueprintType = false;
|
||||
Req.Blueprintable = true;
|
||||
Req.AllowContainer = false;
|
||||
UClass* NewParentClassObj = UWingTypes::TextToOneObjectType(Parent, Req);
|
||||
UClass* NewParentClassObj = UWingTypes::TextToOneObjectType(Parent, Req, WingOut::Stdout);
|
||||
if (!NewParentClassObj) return;
|
||||
|
||||
// Validate reparent
|
||||
if (!WingUtils::CanReparentBlueprint(BP->GeneratedClass, NewParentClassObj))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Error: Cannot reparent %s to %s — incompatible class hierarchy.\n"),
|
||||
WingOut::Stdout.Printf(TEXT("Error: Cannot reparent %s to %s — incompatible class hierarchy.\n"),
|
||||
*WingUtils::FormatName(BP), *WingUtils::FormatName(NewParentClassObj));
|
||||
return;
|
||||
}
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
FBlueprintEditorUtils::RefreshAllNodes(BP);
|
||||
FKismetEditorUtilities::CompileBlueprint(BP);
|
||||
|
||||
UWingServer::Printf(TEXT("Reparented %s -> %s\n"),
|
||||
WingOut::Stdout.Printf(TEXT("Reparented %s -> %s\n"),
|
||||
*WingUtils::FormatName(BP), *WingUtils::FormatName(NewParentClassObj));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
if (!WingFactories::CheckNewAssetPath(Path)) return;
|
||||
if (!WingFactories::CheckNewAssetPath(Path, WingOut::Stdout)) return;
|
||||
|
||||
// Resolve parent class, if specified.
|
||||
UClass *ParentClassObj = nullptr;
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
Req.BlueprintType = false;
|
||||
Req.Blueprintable = true;
|
||||
Req.AllowContainer = false;
|
||||
ParentClassObj = UWingTypes::TextToOneObjectType(ParentClass, Req);
|
||||
ParentClassObj = UWingTypes::TextToOneObjectType(ParentClass, Req, WingOut::Stdout);
|
||||
if (!ParentClassObj) return;
|
||||
}
|
||||
|
||||
@@ -76,26 +76,26 @@ public:
|
||||
UFactory *Factory = NewObject<UFactory>(GetTransientPackage(), FactoryClass);
|
||||
if (Factory == nullptr)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: factory creation failed (bug)\n"));
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: factory creation failed (bug)\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the 'ParentClass' property.
|
||||
WingPropHandle Props;
|
||||
TSharedPtr<IPropertyHandle> PCProp = Props.NamedProperty(Factory, TEXT("ParentClass"), true);
|
||||
TSharedPtr<IPropertyHandle> PCProp = Props.NamedProperty(Factory, TEXT("ParentClass"), true, WingOut::Stdout);
|
||||
if (!PCProp) return;
|
||||
|
||||
// Store the parent class.
|
||||
FPropertyAccess::Result SetResult = PCProp->SetValue(ParentClassObj);
|
||||
if (SetResult != FPropertyAccess::Result::Success)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: property does not allow value: %s\n"), *ParentClass);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: property does not allow value: %s\n"), *ParentClass);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the asset using the factory.
|
||||
UObject *Blueprint = WingFactories::CreateAsset(Path, Factory);
|
||||
UObject *Blueprint = WingFactories::CreateAsset(Path, Factory, WingOut::Stdout);
|
||||
if (Blueprint == nullptr) return;
|
||||
UWingServer::Printf(TEXT("Created.\n"));
|
||||
WingOut::Stdout.Printf(TEXT("Created.\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
{
|
||||
UClass* FactoryClass = Cast<UClass>(ConfigurationObject);
|
||||
UFactory* Factory = NewObject<UFactory>(GetTransientPackage(), FactoryClass);
|
||||
WingFactories::CreateAsset(Path, Factory);
|
||||
UWingServer::Printf(TEXT("Created.\n"));
|
||||
WingFactories::CreateAsset(Path, Factory, WingOut::Stdout);
|
||||
WingOut::Stdout.Printf(TEXT("Created.\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -18,9 +18,6 @@ public:
|
||||
UPROPERTY(EditAnywhere, meta=(Description="Target object"))
|
||||
FString Object;
|
||||
|
||||
UPROPERTY(meta=(Optional, Description="Substring filter for property names"))
|
||||
FString Query;
|
||||
|
||||
virtual void Register() override
|
||||
{
|
||||
UWingServer::AddHandler(this,
|
||||
@@ -29,12 +26,11 @@ public:
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UObject* Target = F.Walk(Object).Cast<UObject>();
|
||||
if (!Target) return;
|
||||
|
||||
TArray<FWingProperty> Props = FWingProperty::GetDetailsImmutable(Target, CPF_Edit);
|
||||
Props = FWingProperty::FindAllSubstring(Props, Query);
|
||||
TArray<FWingProperty> Props = FWingProperty::GetDetails(Target, CPF_Edit, false);
|
||||
|
||||
// Group by category, preserving within-category order.
|
||||
TSortedMap<FString, TArray<FWingProperty>> Categories;
|
||||
@@ -45,14 +41,13 @@ public:
|
||||
Categories.FindOrAdd(Category).Add(P);
|
||||
}
|
||||
|
||||
FStringBuilderBase& Out = UWingServer::GetPrintBuffer();
|
||||
for (const auto& Pair : Categories)
|
||||
{
|
||||
Out.Appendf(TEXT("\n%s:\n"), *Pair.Key);
|
||||
WingOut::Stdout.Printf(TEXT("\n%s:\n"), *Pair.Key);
|
||||
for (const FWingProperty& P : Pair.Value)
|
||||
{
|
||||
bool bEditable = !P->HasAnyPropertyFlags(CPF_EditConst);
|
||||
Out.Appendf(TEXT(" %s %s %s = %s\n"),
|
||||
WingOut::Stdout.Printf(TEXT(" %s %s %s = %s\n"),
|
||||
bEditable ? TEXT("editable") : TEXT("readonly"),
|
||||
*UWingTypes::TypeToText(P.Prop),
|
||||
*WingUtils::FormatName(P.Prop),
|
||||
|
||||
@@ -28,14 +28,14 @@ public:
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UObject* Obj = F.Walk(Object).Cast<UObject>();
|
||||
if (!Obj) return;
|
||||
|
||||
TArray<FWingProperty> Props = FWingProperty::GetDetailsImmutable(Obj, CPF_Edit);
|
||||
FWingProperty* P = WingUtils::FindOneWithExternalID(Property, Props, TEXT("Property"));
|
||||
TArray<FWingProperty> Props = FWingProperty::GetDetails(Obj, CPF_Edit, false);
|
||||
FWingProperty* P = WingUtils::FindOneWithExternalID(Property, Props, TEXT("Property"), WingOut::Stdout);
|
||||
if (!P) return;
|
||||
|
||||
UWingServer::Print(P->GetText());
|
||||
WingOut::Stdout.Print(P->GetText());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -31,15 +31,15 @@ public:
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UObject* Obj = F.Walk(Object).Cast<UObject>();
|
||||
if (!Obj) return;
|
||||
|
||||
TArray<FWingProperty> Props = FWingProperty::GetDetailsMutable(Obj, CPF_Edit);
|
||||
FWingProperty* P = WingUtils::FindOneWithExternalID(Property, Props, TEXT("Property"));
|
||||
TArray<FWingProperty> Props = FWingProperty::GetDetails(Obj, CPF_Edit, true);
|
||||
FWingProperty* P = WingUtils::FindOneWithExternalID(Property, Props, TEXT("Property"), WingOut::Stdout);
|
||||
if (!P) return;
|
||||
|
||||
if (P->SetText(Value))
|
||||
UWingServer::Print(TEXT("OK\n"));
|
||||
if (P->SetText(Value, WingOut::Stdout))
|
||||
WingOut::Stdout.Print(TEXT("OK\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -28,22 +28,22 @@ public:
|
||||
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UObject* Obj = F.Walk(Object).Cast<UObject>();
|
||||
if (!Obj) return;
|
||||
|
||||
if (!Properties.Json || Properties.Json->Values.Num() == 0)
|
||||
{
|
||||
UWingServer::Print(TEXT("Error: No properties specified\n"));
|
||||
WingOut::Stdout.Print(TEXT("Error: No properties specified\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
TArray<FWingProperty> Props = FWingProperty::GetDetailsMutable(Obj, CPF_Edit);
|
||||
TArray<FWingProperty> Props = FWingProperty::GetDetails(Obj, CPF_Edit, true);
|
||||
|
||||
// Validation pass — resolve all properties before modifying anything.
|
||||
for (const auto& Pair : Properties.Json->Values)
|
||||
{
|
||||
FWingProperty* P = WingUtils::FindOneWithExternalID(Pair.Key, Props, TEXT("Property"));
|
||||
FWingProperty* P = WingUtils::FindOneWithExternalID(Pair.Key, Props, TEXT("Property"), WingOut::Stdout);
|
||||
if (!P) return;
|
||||
}
|
||||
|
||||
@@ -51,10 +51,10 @@ public:
|
||||
int SuccessCount = 0;
|
||||
for (const auto& Pair : Properties.Json->Values)
|
||||
{
|
||||
FWingProperty* P = WingUtils::FindOneWithExternalID(Pair.Key, Props, TEXT("Property"));
|
||||
if (P->SetJson(Pair.Value)) SuccessCount++;
|
||||
FWingProperty* P = WingUtils::FindOneWithExternalID(Pair.Key, Props, TEXT("Property"), WingOut::Stdout);
|
||||
if (P->SetJson(*Pair.Value, WingOut::Stdout)) SuccessCount++;
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Set %d/%d properties.\n"), SuccessCount, Properties.Json->Values.Num());
|
||||
WingOut::Stdout.Printf(TEXT("Set %d/%d properties.\n"), SuccessCount, Properties.Json->Values.Num());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -28,14 +28,14 @@ public:
|
||||
UAssetEditorSubsystem* Sub = GEditor->GetEditorSubsystem<UAssetEditorSubsystem>();
|
||||
if (!Sub)
|
||||
{
|
||||
UWingServer::Print(TEXT("Error: AssetEditorSubsystem not available\n"));
|
||||
WingOut::Stdout.Print(TEXT("Error: AssetEditorSubsystem not available\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
TArray<UObject*> EditedAssets = Sub->GetAllEditedAssets();
|
||||
if (EditedAssets.IsEmpty())
|
||||
{
|
||||
UWingServer::Print(TEXT("No asset editors are open.\n"));
|
||||
WingOut::Stdout.Print(TEXT("No asset editors are open.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
{
|
||||
bool bDirty = Asset->GetOutermost()->IsDirty();
|
||||
|
||||
UWingServer::Printf(TEXT(" %s%s\n"),
|
||||
WingOut::Stdout.Printf(TEXT(" %s%s\n"),
|
||||
bDirty ? TEXT("[unsaved] ") : TEXT(""),
|
||||
*Asset->GetPathName());
|
||||
}
|
||||
|
||||
@@ -29,20 +29,20 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UObject* Obj = F.Walk(Asset).Cast<UObject>();
|
||||
if (!Obj) return;
|
||||
|
||||
UAssetEditorSubsystem* Sub = GEditor->GetEditorSubsystem<UAssetEditorSubsystem>();
|
||||
if (!Sub)
|
||||
{
|
||||
UWingServer::Print(TEXT("Error: AssetEditorSubsystem not available\n"));
|
||||
WingOut::Stdout.Print(TEXT("Error: AssetEditorSubsystem not available\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Sub->OpenEditorForAsset(Obj))
|
||||
UWingServer::Printf(TEXT("Opened editor for %s\n"), *Obj->GetPathName());
|
||||
WingOut::Stdout.Printf(TEXT("Opened editor for %s\n"), *Obj->GetPathName());
|
||||
else
|
||||
UWingServer::Printf(TEXT("Error: Could not open editor for %s\n"), *Obj->GetPathName());
|
||||
WingOut::Stdout.Printf(TEXT("Error: Could not open editor for %s\n"), *Obj->GetPathName());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -37,27 +37,27 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
// Check for valid proposed name
|
||||
FName InternalID = WingUtils::CheckProposedName(Dispatcher);
|
||||
FName InternalID = WingUtils::CheckProposedName(Dispatcher, WingOut::Stdout);
|
||||
if (InternalID.IsNone()) return;
|
||||
TSet<FName> Names;
|
||||
FBlueprintEditorUtils::GetClassVariableList(BP, Names);
|
||||
if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("variable or component"))) return;
|
||||
if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("variable or component"), WingOut::Stdout)) return;
|
||||
|
||||
// Parse the arguments.
|
||||
WingVariables Vars;
|
||||
if (!Vars.InputVariables.ParseString(InputVariables)) return;
|
||||
if (!Vars.InputVariables.ParseString(InputVariables, WingOut::Stdout)) return;
|
||||
|
||||
// Add the delegate variable
|
||||
FEdGraphPinType DelegateType;
|
||||
DelegateType.PinCategory = UEdGraphSchema_K2::PC_MCDelegate;
|
||||
if (!FBlueprintEditorUtils::AddMemberVariable(BP, InternalID, DelegateType))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to add event dispatcher '%s' to %s\n"), *Dispatcher, *WingUtils::FormatName(BP));
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Failed to add event dispatcher '%s' to %s\n"), *Dispatcher, *WingUtils::FormatName(BP));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
UEdGraph::StaticClass(), UEdGraphSchema_K2::StaticClass());
|
||||
if (!SigGraph)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to create signature graph for '%s'\n"), *Dispatcher);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Failed to create signature graph for '%s'\n"), *Dispatcher);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -79,9 +79,9 @@ public:
|
||||
BP->DelegateSignatureGraphs.Add(SigGraph);
|
||||
|
||||
// Store the function arguments
|
||||
if (!Vars.SetBackingStore(SigGraph)) return;
|
||||
if (!Vars.Check()) return;
|
||||
if (!Vars.Create()) return;
|
||||
UWingServer::Printf(TEXT("Created event dispatcher %s in %s\n"), *Dispatcher, *WingUtils::FormatName(BP));
|
||||
if (!Vars.SetBackingStore(SigGraph, WingOut::Stdout)) return;
|
||||
if (!Vars.Check(WingOut::Stdout)) return;
|
||||
if (!Vars.Create(WingOut::Stdout)) return;
|
||||
WingOut::Stdout.Printf(TEXT("Created event dispatcher %s in %s\n"), *Dispatcher, *WingUtils::FormatName(BP));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -33,13 +33,13 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||
if (!BP) return;
|
||||
|
||||
FBPVariableDescription* Var = WingUtils::FindOneWithExternalID(Dispatcher, BP->NewVariables, TEXT("Dispatcher"));
|
||||
FBPVariableDescription* Var = WingUtils::FindOneWithExternalID(Dispatcher, BP->NewVariables, TEXT("Dispatcher"), WingOut::Stdout);
|
||||
if (!Var) return;
|
||||
TObjectPtr<UEdGraph>* SigGraph = WingUtils::FindOneWithExternalID(Dispatcher, BP->DelegateSignatureGraphs, TEXT("Dispatcher Signature Graph"));
|
||||
TObjectPtr<UEdGraph>* SigGraph = WingUtils::FindOneWithExternalID(Dispatcher, BP->DelegateSignatureGraphs, TEXT("Dispatcher Signature Graph"), WingOut::Stdout);
|
||||
if (!SigGraph) return;
|
||||
|
||||
UEdGraph* Graph = *SigGraph;
|
||||
@@ -51,6 +51,6 @@ public:
|
||||
// Remove the signature graph
|
||||
FBlueprintEditorUtils::RemoveGraph(BP, Graph, EGraphRemoveFlags::Recompile);
|
||||
|
||||
UWingServer::Printf(TEXT("Deleted event dispatcher %s from %s\n"), *Dispatcher, *WingUtils::FormatName(BP));
|
||||
WingOut::Stdout.Printf(TEXT("Deleted event dispatcher %s from %s\n"), *Dispatcher, *WingUtils::FormatName(BP));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
private:
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UEdGraphNode* NodeObj = F.Walk(Node).Cast<UEdGraphNode>();
|
||||
if (!NodeObj) return;
|
||||
|
||||
@@ -49,15 +49,15 @@ private:
|
||||
|
||||
if (WingToolMenu::Execute(Entry, Context))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Executed: %s\n"), *LabelText);
|
||||
WingOut::Stdout.Printf(TEXT("Executed: %s\n"), *LabelText);
|
||||
}
|
||||
else
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Action '%s' cannot execute (greyed out)\n"), *LabelText);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Action '%s' cannot execute (greyed out)\n"), *LabelText);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("ERROR: Menu item '%s' not found. Use GraphNode_ShowMenu to see available items.\n"), *Item);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Menu item '%s' not found. Use GraphNode_ShowMenu to see available items.\n"), *Item);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -30,6 +30,8 @@ struct FSpawnNodeEntry
|
||||
|
||||
UPROPERTY()
|
||||
int32 PosY = 0;
|
||||
|
||||
FWingGraphAction *Action;
|
||||
};
|
||||
|
||||
|
||||
@@ -53,50 +55,40 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UEdGraph* TargetGraph = F.Walk(Graph).Cast<UEdGraph>();
|
||||
if (!TargetGraph) return;
|
||||
|
||||
int32 SuccessCount = 0;
|
||||
int32 TotalCount = Nodes.Array.Num();
|
||||
FWingGraphActions GraphActions(TargetGraph);
|
||||
|
||||
for (const TSharedPtr<FJsonValue>& NodeVal : Nodes.Array)
|
||||
|
||||
// Parse the json array, turning it into an array of spawn node entries.
|
||||
TArray<FSpawnNodeEntry> Entries;
|
||||
FSpawnNodeEntry Entry;
|
||||
TArray<FWingProperty> Props = FWingProperty::GetAll(&Entry, CPF_None);
|
||||
for (const TSharedPtr<FJsonValue>& Elt : Nodes.Array)
|
||||
{
|
||||
FSpawnNodeEntry Entry;
|
||||
if (!FWingProperty::PopulateFromJson(FSpawnNodeEntry::StaticStruct(), &Entry, NodeVal))
|
||||
continue;
|
||||
|
||||
// Find the action by exact full name
|
||||
if (!FWingProperty::PopulateFromJson(Props, *Elt, false, WingOut::Stdout)) return;
|
||||
TArray<FWingGraphAction*> Results = GraphActions.Search(Entry.ActionName, 2, true);
|
||||
if (Results.Num() == 0)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: No action found matching '%s'. Use GraphNode_SearchTypes to find available actions.\n"),
|
||||
*Entry.ActionName);
|
||||
continue;
|
||||
}
|
||||
if (Results.Num() > 1)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: More than one action matches '%s'.\n"), *Entry.ActionName);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Perform the action
|
||||
UEdGraphNode* NewNode = Results[0]->Execute(FVector2D(Entry.PosX, Entry.PosY));
|
||||
if (!NewNode)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Execute returned null for '%s'.\n"), *Entry.ActionName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!NewNode->NodeGuid.IsValid())
|
||||
NewNode->CreateNewGuid();
|
||||
|
||||
UWingServer::Printf(TEXT("Spawned: %s (%s)\n"),
|
||||
*WingUtils::FormatName(NewNode), *WingUtils::FormatName(NewNode->GetClass()));
|
||||
SuccessCount++;
|
||||
if (!WingUtils::CheckExactlyOneNamed(Results.Num(), TEXT("node type"), Entry.ActionName, WingOut::Stdout)) return;
|
||||
Entry.Action = Results[0];
|
||||
Entries.Add(Entry);
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Spawned %d/%d nodes.\n"), SuccessCount, TotalCount);
|
||||
// Execute all.
|
||||
for (const FSpawnNodeEntry &Entry : Entries)
|
||||
{
|
||||
UEdGraphNode* NewNode = Entry.Action->Execute(FVector2D(Entry.PosX, Entry.PosY));
|
||||
if (NewNode)
|
||||
{
|
||||
WingOut::Stdout.Printf(TEXT("Spawned: %s %s\n"), *Entry.ActionName, *WingUtils::FormatName(NewNode));
|
||||
}
|
||||
else
|
||||
{
|
||||
WingOut::Stdout.Printf(TEXT("FAILED: %s\n"), *Entry.ActionName);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UEdGraphNode* FoundNode = F.Walk(Node).Cast<UEdGraphNode>();
|
||||
if (!FoundNode) return;
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
if (!FoundNode->CanUserDeleteNode())
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Cannot delete node '%s' in graph '%s' — it is not deletable.\n"),
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Cannot delete node '%s' in graph '%s' — it is not deletable.\n"),
|
||||
*NodeTitle, *GraphName);
|
||||
return;
|
||||
}
|
||||
@@ -63,6 +63,6 @@ public:
|
||||
Graph->RemoveNode(FoundNode);
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Deleted node '%s' from graph '%s'.\n"), *NodeTitle, *GraphName);
|
||||
WingOut::Stdout.Printf(TEXT("Deleted node '%s' from graph '%s'.\n"), *NodeTitle, *GraphName);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -29,12 +29,12 @@ public:
|
||||
private:
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UEdGraphNode* NodeObj = F.Walk(Node).Cast<UEdGraphNode>();
|
||||
if (!NodeObj) return;
|
||||
|
||||
WingGraphExport Exporter(NodeObj);
|
||||
UWingServer::Print(*Exporter.GetOutput());
|
||||
UWingServer::Print(Exporter.GetDetails());
|
||||
WingOut::Stdout.Print(*Exporter.GetOutput());
|
||||
WingOut::Stdout.Print(Exporter.GetDetails());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -29,12 +29,12 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UEdGraphNode* FoundNode = F.Walk(Node).Cast<UEdGraphNode>();
|
||||
if (!FoundNode) return;
|
||||
|
||||
UWingServer::Printf(TEXT("Node: %s\n"), *WingUtils::FormatName(FoundNode));
|
||||
UWingServer::Printf(TEXT("Comment: %s\n"), *FoundNode->NodeComment);
|
||||
UWingServer::Printf(TEXT("BubbleVisible: %s\n"), FoundNode->bCommentBubbleVisible ? TEXT("true") : TEXT("false"));
|
||||
WingOut::Stdout.Printf(TEXT("Node: %s\n"), *WingUtils::FormatName(FoundNode));
|
||||
WingOut::Stdout.Printf(TEXT("Comment: %s\n"), *FoundNode->NodeComment);
|
||||
WingOut::Stdout.Printf(TEXT("BubbleVisible: %s\n"), FoundNode->bCommentBubbleVisible ? TEXT("true") : TEXT("false"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -33,13 +33,13 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UEdGraphNode* FoundNode = F.Walk(Node).Cast<UEdGraphNode>();
|
||||
if (!FoundNode) return;
|
||||
|
||||
if (!WingUtils::CheckCanRename(FoundNode, Name)) return;
|
||||
if (!WingUtils::CheckCanRename(FoundNode, Name, WingOut::Stdout)) return;
|
||||
FoundNode->OnRenameNode(Name);
|
||||
|
||||
UWingServer::Printf(TEXT("Renamed node to %s\n"), *Name);
|
||||
WingOut::Stdout.Printf(TEXT("Renamed node to %s\n"), *Name);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UEdGraph* TargetGraph = F.Walk(Graph).Cast<UEdGraph>();
|
||||
if (!TargetGraph) return;
|
||||
|
||||
@@ -47,16 +47,16 @@ public:
|
||||
TArray<FWingGraphAction*> Results = GraphActions.Search(Query, MaxResults, false);
|
||||
for (const FWingGraphAction* Action : Results)
|
||||
{
|
||||
UWingServer::Printf(TEXT("%s\n"), *Action->Name);
|
||||
WingOut::Stdout.Printf(TEXT("%s\n"), *Action->Name);
|
||||
}
|
||||
|
||||
if (Results.Num() == 0)
|
||||
{
|
||||
UWingServer::Print(TEXT("No matching node types found.\n"));
|
||||
WingOut::Stdout.Print(TEXT("No matching node types found.\n"));
|
||||
}
|
||||
else if (Results.Num() >= MaxResults)
|
||||
{
|
||||
UWingServer::Printf(TEXT("WARNING: Reached limit of %d results. You may specify MaxResults.\n"), MaxResults);
|
||||
WingOut::Stdout.Printf(TEXT("WARNING: Reached limit of %d results. You may specify MaxResults.\n"), MaxResults);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UEdGraphNode* FoundNode = F.Walk(Node).Cast<UEdGraphNode>();
|
||||
if (!FoundNode) return;
|
||||
|
||||
@@ -41,6 +41,6 @@ public:
|
||||
FoundNode->bCommentBubbleVisible = !Comment.IsEmpty();
|
||||
FoundNode->bCommentBubblePinned = !Comment.IsEmpty();
|
||||
|
||||
UWingServer::Printf(TEXT("Comment set on %s\n"), *WingUtils::FormatName(FoundNode));
|
||||
WingOut::Stdout.Printf(TEXT("Comment set on %s\n"), *WingUtils::FormatName(FoundNode));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
|
||||
void HandleK2Entry(const FSetNodeDefaultEntry& Entry, UEdGraph* GraphObj, const UEdGraphSchema_K2* K2Schema)
|
||||
{
|
||||
WingFetcher F(GraphObj);
|
||||
WingFetcher F(GraphObj, WingOut::Stdout);
|
||||
UEdGraphPin* Pin = F.Node(Entry.Node).Pin(Entry.Name).Cast<UEdGraphPin>();
|
||||
if (!Pin) return;
|
||||
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
|
||||
if (Pin->Direction != EGPD_Input)
|
||||
{
|
||||
UWingServer::Printf(TEXT("error: %s is an output pin\n"), *WingUtils::FormatName(Pin));
|
||||
WingOut::Stdout.Printf(TEXT("error: %s is an output pin\n"), *WingUtils::FormatName(Pin));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
FString Error = K2Schema->IsPinDefaultValid(Pin, UseDefaultValue, UseDefaultObject, UseDefaultText);
|
||||
if (!Error.IsEmpty())
|
||||
{
|
||||
UWingServer::Printf(TEXT("error: %s: %s\n"), *WingUtils::FormatName(Pin), *Error);
|
||||
WingOut::Stdout.Printf(TEXT("error: %s: %s\n"), *WingUtils::FormatName(Pin), *Error);
|
||||
return;
|
||||
}
|
||||
UWingServer::AddTouchedObject(Node);
|
||||
@@ -87,17 +87,17 @@ public:
|
||||
|
||||
void HandleMaterialEntry(const FSetNodeDefaultEntry& Entry, UEdGraph* GraphObj)
|
||||
{
|
||||
WingFetcher F(GraphObj);
|
||||
WingFetcher F(GraphObj, WingOut::Stdout);
|
||||
UEdGraphNode* Node = F.Node(Entry.Node).Cast<UEdGraphNode>();
|
||||
if (!Node) return;
|
||||
|
||||
TArray<FWingProperty> All = FWingProperty::GetDetailsMutable(Node, CPF_Edit);
|
||||
FWingProperty *P = WingUtils::FindOneWithExternalID(Entry.Name, All, TEXT("Property"));
|
||||
TArray<FWingProperty> All = FWingProperty::GetDetails(Node, CPF_Edit, true);
|
||||
FWingProperty *P = WingUtils::FindOneWithExternalID(Entry.Name, All, TEXT("Property"), WingOut::Stdout);
|
||||
if (!P) return;
|
||||
|
||||
UWingServer::AddTouchedObject(Node);
|
||||
|
||||
if (!P->SetText(Entry.Value))
|
||||
if (!P->SetText(Entry.Value, WingOut::Stdout))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public:
|
||||
virtual void Handle() override
|
||||
{
|
||||
// Fetch the graph once.
|
||||
WingFetcher GraphFetcher;
|
||||
WingFetcher GraphFetcher(WingOut::Stdout);
|
||||
UEdGraph* GraphObj = GraphFetcher.Walk(Graph).Cast<UEdGraph>();
|
||||
if (!GraphObj) return;
|
||||
|
||||
@@ -116,22 +116,19 @@ public:
|
||||
|
||||
if (!K2Schema && !MGSchema)
|
||||
{
|
||||
UWingServer::Printf(TEXT("error: unsupported graph schema %s\n"), *Schema->GetClass()->GetName());
|
||||
WingOut::Stdout.Printf(TEXT("error: unsupported graph schema %s\n"), *Schema->GetClass()->GetName());
|
||||
return;
|
||||
}
|
||||
|
||||
FSetNodeDefaultEntry Entry;
|
||||
TArray<FWingProperty> Props = FWingProperty::GetAll(&Entry, CPF_None);
|
||||
for (const TSharedPtr<FJsonValue>& PinVal : Pins.Array)
|
||||
{
|
||||
FSetNodeDefaultEntry Entry;
|
||||
if (!FWingProperty::PopulateFromJson(FSetNodeDefaultEntry::StaticStruct(), &Entry, PinVal))
|
||||
continue;
|
||||
|
||||
if (K2Schema)
|
||||
HandleK2Entry(Entry, GraphObj, K2Schema);
|
||||
else if (MGSchema)
|
||||
HandleMaterialEntry(Entry, GraphObj);
|
||||
if (!FWingProperty::PopulateFromJson(Props, *PinVal, false, WingOut::Stdout)) continue;
|
||||
if (K2Schema) HandleK2Entry(Entry, GraphObj, K2Schema);
|
||||
else if (MGSchema) HandleMaterialEntry(Entry, GraphObj);
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Done.\n"));
|
||||
WingOut::Stdout.Printf(TEXT("Done.\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFetcher.h"
|
||||
#include "WingProperty.h"
|
||||
#include "WingUtils.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "EdGraph/EdGraphNode.h"
|
||||
@@ -49,26 +50,25 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UEdGraph* TargetGraph = F.Walk(Graph).Cast<UEdGraph>();
|
||||
if (!TargetGraph) return;
|
||||
|
||||
int32 SuccessCount = 0;
|
||||
|
||||
for (const TSharedPtr<FJsonValue>& NodeVal : Nodes.Array)
|
||||
FMoveNodeEntry Entry;
|
||||
TArray<FWingProperty> Props = FWingProperty::GetAll(&Entry, CPF_None);
|
||||
for (const TSharedPtr<FJsonValue>& Elt : Nodes.Array)
|
||||
{
|
||||
FMoveNodeEntry Entry;
|
||||
if (!FWingProperty::PopulateFromJson(FMoveNodeEntry::StaticStruct(), &Entry, NodeVal)) continue;
|
||||
|
||||
WingFetcher FN(TargetGraph);
|
||||
if (!FWingProperty::PopulateFromJson(Props, *Elt, false, WingOut::Stdout)) continue;
|
||||
WingFetcher FN(TargetGraph, WingOut::Stdout);
|
||||
UEdGraphNode* Node = FN.Node(Entry.Node).Cast<UEdGraphNode>();
|
||||
if (!Node) continue;
|
||||
|
||||
Node->NodePosX = Entry.X;
|
||||
Node->NodePosY = Entry.Y;
|
||||
SuccessCount++;
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Moved %d/%d nodes.\n"), SuccessCount, Nodes.Array.Num());
|
||||
WingOut::Stdout.Printf(TEXT("Moved %d/%d nodes.\n"), SuccessCount, Nodes.Array.Num());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -31,13 +31,13 @@ public:
|
||||
private:
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UEdGraphNode* NodeObj = F.Walk(Node).Cast<UEdGraphNode>();
|
||||
if (!NodeObj) return;
|
||||
|
||||
if (Cast<UMaterialGraphNode>(NodeObj))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Material graph nodes do not have usable context menus."));
|
||||
WingOut::Stdout.Printf(TEXT("Material graph nodes do not have usable context menus."));
|
||||
return;
|
||||
}
|
||||
FToolMenuContext Context;
|
||||
@@ -45,8 +45,8 @@ private:
|
||||
for (FToolMenuEntry &Entry : Entries)
|
||||
{
|
||||
FString LabelText = Entry.Label.Get().ToString();
|
||||
UWingServer::Printf(TEXT("%s\n"), *LabelText);
|
||||
WingOut::Stdout.Printf(TEXT("%s\n"), *LabelText);
|
||||
}
|
||||
if (Entries.IsEmpty()) UWingServer::Printf(TEXT("No selectable menu entries right now.\n"));
|
||||
if (Entries.IsEmpty()) WingOut::Stdout.Printf(TEXT("No selectable menu entries right now.\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -49,24 +49,25 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UEdGraph* G = F.Walk(Graph).Cast<UEdGraph>();
|
||||
if (!G) return;
|
||||
|
||||
int32 SuccessCount = 0;
|
||||
int32 TotalCount = Connections.Array.Num();
|
||||
|
||||
FConnectPinsEntry Entry;
|
||||
TArray<FWingProperty> EntryProps = FWingProperty::GetAll(&Entry, CPF_None);
|
||||
for (const TSharedPtr<FJsonValue>& ConnVal : Connections.Array)
|
||||
{
|
||||
FConnectPinsEntry Entry;
|
||||
if (!FWingProperty::PopulateFromJson(FConnectPinsEntry::StaticStruct(), &Entry, ConnVal))
|
||||
if (!FWingProperty::PopulateFromJson(EntryProps, *ConnVal, false, WingOut::Stdout))
|
||||
continue;
|
||||
|
||||
WingFetcher FS(G);
|
||||
WingFetcher FS(G, WingOut::Stdout);
|
||||
UEdGraphPin* SourcePin = FS.Walk(Entry.SourcePin).Cast<UEdGraphPin>();
|
||||
if (!SourcePin) continue;
|
||||
|
||||
WingFetcher FT(G);
|
||||
WingFetcher FT(G, WingOut::Stdout);
|
||||
UEdGraphPin* TargetPin = FT.Walk(Entry.TargetPin).Cast<UEdGraphPin>();
|
||||
if (!TargetPin) continue;
|
||||
|
||||
@@ -74,7 +75,7 @@ public:
|
||||
const FPinConnectionResponse Response = Schema->CanCreateConnection(SourcePin, TargetPin);
|
||||
if (Response.Response == CONNECT_RESPONSE_DISALLOW)
|
||||
{
|
||||
UWingServer::Printf(TEXT("error: Cannot connect %s.%s to %s.%s: %s\n"),
|
||||
WingOut::Stdout.Printf(TEXT("error: Cannot connect %s.%s to %s.%s: %s\n"),
|
||||
*WingUtils::FormatName(SourcePin->GetOwningNode()), *WingUtils::FormatName(SourcePin),
|
||||
*WingUtils::FormatName(TargetPin->GetOwningNode()), *WingUtils::FormatName(TargetPin),
|
||||
*Response.Message.ToString());
|
||||
@@ -85,6 +86,6 @@ public:
|
||||
SuccessCount++;
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Connected %d/%d pins.\n"), SuccessCount, TotalCount);
|
||||
WingOut::Stdout.Printf(TEXT("Connected %d/%d pins.\n"), SuccessCount, TotalCount);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -49,19 +49,20 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UEdGraph* G = F.Walk(Graph).Cast<UEdGraph>();
|
||||
if (!G) return;
|
||||
|
||||
int32 SuccessCount = 0;
|
||||
int32 TotalDisconnected = 0;
|
||||
|
||||
FDisconnectPinEntry Entry;
|
||||
TArray<FWingProperty> EntryProps = FWingProperty::GetAll(&Entry, CPF_None);
|
||||
for (const TSharedPtr<FJsonValue>& DiscVal : Disconnections.Array)
|
||||
{
|
||||
FDisconnectPinEntry Entry;
|
||||
if (!FWingProperty::PopulateFromJson(FDisconnectPinEntry::StaticStruct(), &Entry, DiscVal)) continue;
|
||||
if (!FWingProperty::PopulateFromJson(EntryProps, *DiscVal, false, WingOut::Stdout)) continue;
|
||||
|
||||
WingFetcher FP(G);
|
||||
WingFetcher FP(G, WingOut::Stdout);
|
||||
UEdGraphPin* Pin = FP.Walk(Entry.Pin).Cast<UEdGraphPin>();
|
||||
if (!Pin) continue;
|
||||
|
||||
@@ -69,13 +70,13 @@ public:
|
||||
|
||||
if (!Entry.TargetPin.IsEmpty())
|
||||
{
|
||||
WingFetcher FT(G);
|
||||
WingFetcher FT(G, WingOut::Stdout);
|
||||
UEdGraphPin* Target = FT.Walk(Entry.TargetPin).Cast<UEdGraphPin>();
|
||||
if (!Target) continue;
|
||||
|
||||
if (!Pin->LinkedTo.Contains(Target))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Error: %s.%s is not connected to %s.%s\n"),
|
||||
WingOut::Stdout.Printf(TEXT("Error: %s.%s is not connected to %s.%s\n"),
|
||||
*WingUtils::FormatName(Pin->GetOwningNode()), *WingUtils::FormatName(Pin),
|
||||
*WingUtils::FormatName(Target->GetOwningNode()), *WingUtils::FormatName(Target));
|
||||
continue;
|
||||
@@ -93,14 +94,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Disconnected %d link(s) from %s.%s\n"),
|
||||
WingOut::Stdout.Printf(TEXT("Disconnected %d link(s) from %s.%s\n"),
|
||||
DisconnectedCount,
|
||||
*WingUtils::FormatName(Pin->GetOwningNode()), *WingUtils::FormatName(Pin));
|
||||
SuccessCount++;
|
||||
TotalDisconnected += DisconnectedCount;
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Done: %d/%d succeeded, %d links broken.\n"),
|
||||
WingOut::Stdout.Printf(TEXT("Done: %d/%d succeeded, %d links broken.\n"),
|
||||
SuccessCount, Disconnections.Array.Num(), TotalDisconnected);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -36,19 +36,19 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UEdGraph *G = F.Walk(Graph).Cast<UEdGraph>();
|
||||
if (!G) return;
|
||||
|
||||
WingGraphExport Exporter(G);
|
||||
UWingServer::Print(*Exporter.GetOutput());
|
||||
WingOut::Stdout.Print(*Exporter.GetOutput());
|
||||
if (IncludeDetails)
|
||||
{
|
||||
UWingServer::Print(Exporter.GetDetails());
|
||||
WingOut::Stdout.Print(Exporter.GetDetails());
|
||||
}
|
||||
else
|
||||
{
|
||||
UWingServer::Printf(TEXT("\nNote: use bDetails=true to see suppressed details."));
|
||||
WingOut::Stdout.Printf(TEXT("\nNote: use bDetails=true to see suppressed details."));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -40,13 +40,13 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UMaterialInstanceConstant* MI = F.Asset(MaterialInstance).Cast<UMaterialInstanceConstant>();
|
||||
if (!MI) return;
|
||||
|
||||
// Parse the association string.
|
||||
EMaterialParameterAssociation Association;
|
||||
if (!WingMaterialParameter::ParseMaterialParameterAssociation(ParameterAssociation, Association))
|
||||
if (!WingMaterialParameter::ParseMaterialParameterAssociation(ParameterAssociation, Association, WingOut::Stdout))
|
||||
return;
|
||||
|
||||
FMaterialParameterInfo ParamID(*Parameter, Association, ParameterLayer);
|
||||
@@ -68,12 +68,12 @@ public:
|
||||
|
||||
if (Removed == 0)
|
||||
{
|
||||
UWingServer::Printf(TEXT("No override found for parameter '%s' (association=%s layer=%d) on %s"),
|
||||
WingOut::Stdout.Printf(TEXT("No override found for parameter '%s' (association=%s layer=%d) on %s"),
|
||||
*Parameter, *ParameterAssociation, ParameterLayer, *WingUtils::FormatName(MI));
|
||||
return;
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Cleared override for '%s' on %s\n"),
|
||||
WingOut::Stdout.Printf(TEXT("Cleared override for '%s' on %s\n"),
|
||||
*Parameter, *WingUtils::FormatName(MI));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UMaterialInstanceConstant* MI = F.Asset(MaterialInstance).Cast<UMaterialInstanceConstant>();
|
||||
if (!MI) return;
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
for (auto& [Info, Meta] : AllParams)
|
||||
{
|
||||
if (!Meta.bOverride) continue;
|
||||
if (!bHasOverrides) { UWingServer::Print(TEXT("\nOverridden Parameters:\n")); bHasOverrides = true; }
|
||||
if (!bHasOverrides) { WingOut::Stdout.Print(TEXT("\nOverridden Parameters:\n")); bHasOverrides = true; }
|
||||
WingMaterialParameter::FormatMaterialParameter(Info, Meta);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
for (auto& [Info, Meta] : AllParams)
|
||||
{
|
||||
if (Meta.bOverride) continue;
|
||||
if (!bHasInherited) { UWingServer::Print(TEXT("\nInherited Parameters (not overridden):\n")); bHasInherited = true; }
|
||||
if (!bHasInherited) { WingOut::Stdout.Print(TEXT("\nInherited Parameters (not overridden):\n")); bHasInherited = true; }
|
||||
WingMaterialParameter::FormatMaterialParameter(Info, Meta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,13 +44,13 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UMaterialInstanceConstant* MI = F.Asset(MaterialInstance).Cast<UMaterialInstanceConstant>();
|
||||
if (!MI) return;
|
||||
|
||||
// Parse the association string.
|
||||
EMaterialParameterAssociation Association;
|
||||
if (!WingMaterialParameter::ParseMaterialParameterAssociation(ParameterAssociation, Association))
|
||||
if (!WingMaterialParameter::ParseMaterialParameterAssociation(ParameterAssociation, Association, WingOut::Stdout))
|
||||
return;
|
||||
|
||||
// Build the parameter ID to look up.
|
||||
@@ -61,13 +61,13 @@ public:
|
||||
FMaterialParameterMetadata* Found = AllParams.Find(ParamID);
|
||||
if (!Found)
|
||||
{
|
||||
UWingServer::Printf(TEXT("No parameter named '%s' with association=%s layer=%d"),
|
||||
WingOut::Stdout.Printf(TEXT("No parameter named '%s' with association=%s layer=%d"),
|
||||
*Parameter, *ParameterAssociation, ParameterLayer);
|
||||
return;
|
||||
}
|
||||
if (Found->PrimitiveDataIndex != INDEX_NONE)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Parameter '%s' uses custom primitive data and cannot be set on a material instance"), *Parameter);
|
||||
WingOut::Stdout.Printf(TEXT("Parameter '%s' uses custom primitive data and cannot be set on a material instance"), *Parameter);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
float ScalarValue;
|
||||
if (!FDefaultValueHelper::ParseFloat(Value, ScalarValue))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Failed to parse '%s' as a float"), *Value);
|
||||
WingOut::Stdout.Printf(TEXT("Failed to parse '%s' as a float"), *Value);
|
||||
return;
|
||||
}
|
||||
MI->SetScalarParameterValueEditorOnly(ParamID, ScalarValue);
|
||||
@@ -91,17 +91,17 @@ public:
|
||||
FLinearColor Color;
|
||||
if (!Color.InitFromString(Value))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Failed to parse '%s' as a color/vector (expected format: '(R=1,G=0,B=0,A=1)')"), *Value);
|
||||
WingOut::Stdout.Printf(TEXT("Failed to parse '%s' as a color/vector (expected format: '(R=1,G=0,B=0,A=1)')"), *Value);
|
||||
return;
|
||||
}
|
||||
MI->SetVectorParameterValueEditorOnly(ParamID, Color);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UWingServer::Printf(TEXT("Parameters of type %d (see EMaterialParameterType) are not implemented"), (int)Type);
|
||||
WingOut::Stdout.Printf(TEXT("Parameters of type %d (see EMaterialParameterType) are not implemented"), (int)Type);
|
||||
return;
|
||||
}
|
||||
UWingServer::Printf(TEXT("Set '%s' = %s on %s\n"),
|
||||
WingOut::Stdout.Printf(TEXT("Set '%s' = %s on %s\n"),
|
||||
*Parameter, *Value, *WingUtils::FormatName(MI));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
virtual void Handle() override
|
||||
{
|
||||
// Load material
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UMaterial* MaterialObj = F.Asset(Material).Cast<UMaterial>();
|
||||
if (!MaterialObj) return;
|
||||
|
||||
@@ -48,14 +48,14 @@ public:
|
||||
|
||||
if (Errors.IsEmpty())
|
||||
{
|
||||
UWingServer::Printf(TEXT("%s compiled successfully.\n"), *WingUtils::FormatName(MaterialObj));
|
||||
WingOut::Stdout.Printf(TEXT("%s compiled successfully.\n"), *WingUtils::FormatName(MaterialObj));
|
||||
}
|
||||
else
|
||||
{
|
||||
UWingServer::Printf(TEXT("%s compiled with %d error(s):\n"), *WingUtils::FormatName(MaterialObj), Errors.Num());
|
||||
WingOut::Stdout.Printf(TEXT("%s compiled with %d error(s):\n"), *WingUtils::FormatName(MaterialObj), Errors.Num());
|
||||
for (const FString& Err : Errors)
|
||||
{
|
||||
UWingServer::Printf(TEXT(" %s\n"), *Err);
|
||||
WingOut::Stdout.Printf(TEXT(" %s\n"), *Err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UMaterial* Mat = F.Asset(Material).Cast<UMaterial>();
|
||||
if (!Mat) return;
|
||||
|
||||
@@ -40,6 +40,6 @@ public:
|
||||
{
|
||||
WingMaterialParameter::FormatMaterialParameter(Info, Meta);
|
||||
}
|
||||
if (AllParams.IsEmpty()) UWingServer::Printf(TEXT("No material parameters.\n"));
|
||||
if (AllParams.IsEmpty()) WingOut::Stdout.Printf(TEXT("No material parameters.\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
if (Group != PrevGroup)
|
||||
{
|
||||
if (!PrevGroup.IsEmpty())
|
||||
UWingServer::Print(TEXT("\n"));
|
||||
WingOut::Stdout.Print(TEXT("\n"));
|
||||
PrevGroup = Group;
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
}
|
||||
if (Kind == EWingHandlerKind::Normal)
|
||||
{
|
||||
UWingServer::Printf(TEXT(
|
||||
WingOut::Stdout.Printf(TEXT(
|
||||
"\n"
|
||||
"You can also use ShowCommands with Kind=Create to see commands that create new assets.\n"
|
||||
"\n"));
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
Results.Sort();
|
||||
for (const FString &Line : Results)
|
||||
{
|
||||
UWingServer::Printf(TEXT("%s\n"), *Line);
|
||||
WingOut::Stdout.Printf(TEXT("%s\n"), *Line);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -27,6 +27,6 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
UWingServer::Printf(TEXT("%s\n"), *WingTokenizer::ExternalizeID(FName(Input)));
|
||||
WingOut::Stdout.Printf(TEXT("%s\n"), *WingTokenizer::ExternalizeID(FName(Input)));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -28,6 +28,6 @@ public:
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingTokenizer T(Input);
|
||||
T.PrintEverything(UWingServer::GetPrintBuffer());
|
||||
T.PrintEverything(WingOut::StdoutBuffer);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -33,22 +33,22 @@ public:
|
||||
Require.Blueprintable = false;
|
||||
Require.AllowContainer = true;
|
||||
|
||||
bool OK = UWingTypes::TextToType(Input, PinType, Require);
|
||||
bool OK = UWingTypes::TextToType(Input, PinType, Require, WingOut::Stdout);
|
||||
|
||||
auto& Out = UWingServer::GetPrintBuffer();
|
||||
Out.Appendf(TEXT("ParseResult: %s\n"), OK ? TEXT("OK") : TEXT("FAILED"));
|
||||
Out.Appendf(TEXT("PinCategory: %s\n"), *PinType.PinCategory.ToString());
|
||||
Out.Appendf(TEXT("PinSubCategory: %s\n"), *PinType.PinSubCategory.ToString());
|
||||
Out.Appendf(TEXT("PinSubCategoryObject: %s\n"),
|
||||
auto& Out = WingOut::Stdout;
|
||||
Out.Printf(TEXT("ParseResult: %s\n"), OK ? TEXT("OK") : TEXT("FAILED"));
|
||||
Out.Printf(TEXT("PinCategory: %s\n"), *PinType.PinCategory.ToString());
|
||||
Out.Printf(TEXT("PinSubCategory: %s\n"), *PinType.PinSubCategory.ToString());
|
||||
Out.Printf(TEXT("PinSubCategoryObject: %s\n"),
|
||||
PinType.PinSubCategoryObject.IsValid()
|
||||
? *PinType.PinSubCategoryObject->GetPathName()
|
||||
: TEXT("(none)"));
|
||||
Out.Appendf(TEXT("ContainerType: %d\n"), (int32)PinType.ContainerType);
|
||||
Out.Printf(TEXT("ContainerType: %d\n"), (int32)PinType.ContainerType);
|
||||
if (PinType.IsMap())
|
||||
{
|
||||
Out.Appendf(TEXT("ValueTerminalCategory: %s\n"), *PinType.PinValueType.TerminalCategory.ToString());
|
||||
Out.Appendf(TEXT("ValueTerminalSubCategory: %s\n"), *PinType.PinValueType.TerminalSubCategory.ToString());
|
||||
Out.Appendf(TEXT("ValueTerminalSubCategoryObject: %s\n"),
|
||||
Out.Printf(TEXT("ValueTerminalCategory: %s\n"), *PinType.PinValueType.TerminalCategory.ToString());
|
||||
Out.Printf(TEXT("ValueTerminalSubCategory: %s\n"), *PinType.PinValueType.TerminalSubCategory.ToString());
|
||||
Out.Printf(TEXT("ValueTerminalSubCategoryObject: %s\n"),
|
||||
PinType.PinValueType.TerminalSubCategoryObject.IsValid()
|
||||
? *PinType.PinValueType.TerminalSubCategoryObject->GetPathName()
|
||||
: TEXT("(none)"));
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
if (OK)
|
||||
{
|
||||
FString RoundTrip = UWingTypes::TypeToText(PinType);
|
||||
Out.Appendf(TEXT("TypeToText: %s\n"), RoundTrip.IsEmpty() ? TEXT("(empty)") : *RoundTrip);
|
||||
Out.Printf(TEXT("TypeToText: %s\n"), RoundTrip.IsEmpty() ? TEXT("(empty)") : *RoundTrip);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -31,11 +31,11 @@ public:
|
||||
FName Result = WingTokenizer::TryInternalizeID(Input, Error);
|
||||
if (!Error.IsEmpty())
|
||||
{
|
||||
UWingServer::Printf(TEXT("Error: %s\n"), *Error);
|
||||
WingOut::Stdout.Printf(TEXT("Error: %s\n"), *Error);
|
||||
}
|
||||
if (!Result.IsNone())
|
||||
{
|
||||
UWingServer::Printf(TEXT("Result: %s\n"), *Result.ToString());
|
||||
WingOut::Stdout.Printf(TEXT("Result: %s\n"), *Result.ToString());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -94,13 +94,13 @@ public:
|
||||
{
|
||||
const UWingTypes::Info& Info = *Matches[i];
|
||||
if (IsProjectDefined(Info))
|
||||
UWingServer::Printf(TEXT("%s (%s, User-Defined)\n"), *Info.Short, *BroadCategory(Info));
|
||||
WingOut::Stdout.Printf(TEXT("%s (%s, User-Defined)\n"), *Info.Short, *BroadCategory(Info));
|
||||
else
|
||||
UWingServer::Printf(TEXT("%s (%s)\n"), *Info.Short, *BroadCategory(Info));
|
||||
WingOut::Stdout.Printf(TEXT("%s (%s)\n"), *Info.Short, *BroadCategory(Info));
|
||||
}
|
||||
if (Count >= Limit)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Search limit reached, raise it with Limit=\n"));
|
||||
WingOut::Stdout.Printf(TEXT("Search limit reached, raise it with Limit=\n"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -40,18 +40,18 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UObject* Obj = F.Walk(Object).Cast<UObject>();
|
||||
if (!Obj) return;
|
||||
|
||||
WingVariables Vars;
|
||||
if (!Vars.SetBackingStore(Obj)) return;
|
||||
if (!Vars.BlueprintVariables.ParseString(BlueprintVariables)) return;
|
||||
if (!Vars.InputVariables.ParseString(InputVariables)) return;
|
||||
if (!Vars.OutputVariables.ParseString(OutputVariables)) return;
|
||||
if (!Vars.LocalVariables.ParseString(LocalVariables)) return;
|
||||
if (!Vars.Check()) return;
|
||||
if (!Vars.Create()) return;
|
||||
UWingServer::Printf(TEXT("Success.\n"));
|
||||
if (!Vars.SetBackingStore(Obj, WingOut::Stdout)) return;
|
||||
if (!Vars.BlueprintVariables.ParseString(BlueprintVariables, WingOut::Stdout)) return;
|
||||
if (!Vars.InputVariables.ParseString(InputVariables, WingOut::Stdout)) return;
|
||||
if (!Vars.OutputVariables.ParseString(OutputVariables, WingOut::Stdout)) return;
|
||||
if (!Vars.LocalVariables.ParseString(LocalVariables, WingOut::Stdout)) return;
|
||||
if (!Vars.Check(WingOut::Stdout)) return;
|
||||
if (!Vars.Create(WingOut::Stdout)) return;
|
||||
WingOut::Stdout.Printf(TEXT("Success.\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -29,13 +29,13 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UObject* Obj = F.Walk(Object).Cast<UObject>();
|
||||
if (!Obj) return;
|
||||
|
||||
WingVariables Vars;
|
||||
if (!Vars.SetBackingStore(Obj)) return;
|
||||
Vars.Load();
|
||||
Vars.Print(UWingServer::GetPrintBuffer());
|
||||
if (!Vars.SetBackingStore(Obj, WingOut::Stdout)) return;
|
||||
Vars.Load(WingOut::Stdout);
|
||||
Vars.Print(WingOut::StdoutBuffer);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -41,18 +41,18 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UObject* Obj = F.Walk(Object).Cast<UObject>();
|
||||
if (!Obj) return;
|
||||
|
||||
WingVariables Vars;
|
||||
if (!Vars.SetBackingStore(Obj)) return;
|
||||
if (!Vars.BlueprintVariables.ParseString(BlueprintVariables)) return;
|
||||
if (!Vars.InputVariables.ParseString(InputVariables)) return;
|
||||
if (!Vars.OutputVariables.ParseString(OutputVariables)) return;
|
||||
if (!Vars.LocalVariables.ParseString(LocalVariables)) return;
|
||||
if (!Vars.Check()) return;
|
||||
if (!Vars.Modify()) return;
|
||||
UWingServer::Printf(TEXT("Success.\n"));
|
||||
if (!Vars.SetBackingStore(Obj, WingOut::Stdout)) return;
|
||||
if (!Vars.BlueprintVariables.ParseString(BlueprintVariables, WingOut::Stdout)) return;
|
||||
if (!Vars.InputVariables.ParseString(InputVariables, WingOut::Stdout)) return;
|
||||
if (!Vars.OutputVariables.ParseString(OutputVariables, WingOut::Stdout)) return;
|
||||
if (!Vars.LocalVariables.ParseString(LocalVariables, WingOut::Stdout)) return;
|
||||
if (!Vars.Check(WingOut::Stdout)) return;
|
||||
if (!Vars.Modify(WingOut::Stdout)) return;
|
||||
WingOut::Stdout.Printf(TEXT("Success.\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -40,17 +40,17 @@ public:
|
||||
}
|
||||
virtual void Handle() override
|
||||
{
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UObject* Obj = F.Walk(Object).Cast<UObject>();
|
||||
if (!Obj) return;
|
||||
|
||||
WingVariables Vars;
|
||||
if (!Vars.SetBackingStore(Obj)) return;
|
||||
if (!Vars.BlueprintVariables.ParseNamesString(BlueprintVariables)) return;
|
||||
if (!Vars.InputVariables.ParseNamesString(InputVariables)) return;
|
||||
if (!Vars.OutputVariables.ParseNamesString(OutputVariables)) return;
|
||||
if (!Vars.LocalVariables.ParseNamesString(LocalVariables)) return;
|
||||
if (!Vars.Remove()) return;
|
||||
UWingServer::Printf(TEXT("Success.\n"));
|
||||
if (!Vars.SetBackingStore(Obj, WingOut::Stdout)) return;
|
||||
if (!Vars.BlueprintVariables.ParseNamesString(BlueprintVariables, WingOut::Stdout)) return;
|
||||
if (!Vars.InputVariables.ParseNamesString(InputVariables, WingOut::Stdout)) return;
|
||||
if (!Vars.OutputVariables.ParseNamesString(OutputVariables, WingOut::Stdout)) return;
|
||||
if (!Vars.LocalVariables.ParseNamesString(LocalVariables, WingOut::Stdout)) return;
|
||||
if (!Vars.Remove(WingOut::Stdout)) return;
|
||||
WingOut::Stdout.Printf(TEXT("Success.\n"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
virtual void Handle() override
|
||||
{
|
||||
// Fetch the widget blueprint.
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UWidgetBlueprint* BP = F.Walk(Blueprint).Cast<UWidgetBlueprint>();
|
||||
if (!BP) return;
|
||||
UWidgetTree* Tree = BP->WidgetTree;
|
||||
@@ -56,18 +56,18 @@ public:
|
||||
// Resolve the widget type.
|
||||
WingWidgets WidgetMenu;
|
||||
TArray<WingWidgets::Type> TypeResults = WidgetMenu.Search(Type, 2, true);
|
||||
if (!WingUtils::CheckExactlyOneNamed(TypeResults.Num(), TEXT("Widget type"), Type)) return;
|
||||
if (!WingUtils::CheckExactlyOneNamed(TypeResults.Num(), TEXT("Widget type"), Type, WingOut::Stdout)) return;
|
||||
|
||||
// Load the widget's class.
|
||||
UClass* WidgetClass = TypeResults[0].Class.LoadSynchronous();
|
||||
if (!WidgetClass)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to load widget class for '%s'\n"), *Type);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Failed to load widget class for '%s'\n"), *Type);
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate the proposed name.
|
||||
FName InternalID = WingUtils::CheckProposedName(Name);
|
||||
FName InternalID = WingUtils::CheckProposedName(Name, WingOut::Stdout);
|
||||
if (InternalID.IsNone()) return;
|
||||
|
||||
// Check that the name is unique among existing widgets.
|
||||
@@ -75,23 +75,23 @@ public:
|
||||
Tree->GetAllWidgets(AllWidgets);
|
||||
TSet<FName> Names;
|
||||
FBlueprintEditorUtils::GetClassVariableList(BP, Names);
|
||||
if (!WingUtils::FindNoDuplicateNames(Names, AllWidgets, TEXT("widget or variable"))) return;
|
||||
if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("widget or variable"))) return;
|
||||
if (!WingUtils::FindNoDuplicateNames(Names, AllWidgets, TEXT("widget or variable"), WingOut::Stdout)) return;
|
||||
if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("widget or variable"), WingOut::Stdout)) return;
|
||||
|
||||
// If a parent is specified, find it and verify it's a panel.
|
||||
UPanelWidget* ParentPanel = nullptr;
|
||||
if (!Parent.IsEmpty())
|
||||
{
|
||||
UWidget* ParentWidget = WingUtils::FindOneWithExternalID(Parent, AllWidgets, TEXT("Widget"));
|
||||
UWidget* ParentWidget = WingUtils::FindOneWithExternalID(Parent, AllWidgets, TEXT("Widget"), WingOut::Stdout);
|
||||
if (!ParentWidget) return;
|
||||
if (!WingWidgets::CheckCanBeParent(ParentWidget)) return;
|
||||
if (!WingWidgets::CheckCanBeParent(ParentWidget, WingOut::Stdout)) return;
|
||||
ParentPanel = Cast<UPanelWidget>(ParentWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Tree->RootWidget != nullptr)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Widget tree already has a root widget. Specify a Parent.\n"));
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Widget tree already has a root widget. Specify a Parent.\n"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
|
||||
if (!NewWidget)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to create widget\n"));
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Failed to create widget\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -123,6 +123,6 @@ public:
|
||||
Tree->RootWidget = NewWidget;
|
||||
}
|
||||
|
||||
UWingServer::Printf(TEXT("Created widget '%s' of type '%s'\n"), *Name, *Type);
|
||||
WingOut::Stdout.Printf(TEXT("Created widget '%s' of type '%s'\n"), *Name, *Type);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
virtual void Handle() override
|
||||
{
|
||||
// Walk to the widget.
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UWidget* TargetWidget = F.Walk(Widget).Cast<UWidget>();
|
||||
if (!TargetWidget) return;
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
UWidgetBlueprint* BP = TargetWidget->GetTypedOuter<UWidgetBlueprint>();
|
||||
if (!BP)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Could not find owning WidgetBlueprint\n"));
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Could not find owning WidgetBlueprint\n"));
|
||||
return;
|
||||
}
|
||||
UWidgetTree* Tree = BP->WidgetTree;
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
{
|
||||
if (Panel->GetChildrenCount() > 0)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Widget '%s' has %d children. Remove them first.\n"),
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Widget '%s' has %d children. Remove them first.\n"),
|
||||
*WingUtils::FormatName(TargetWidget), Panel->GetChildrenCount());
|
||||
return;
|
||||
}
|
||||
@@ -80,6 +80,6 @@ public:
|
||||
// Rename to transient package to avoid name conflicts with future widgets.
|
||||
TargetWidget->Rename(nullptr, GetTransientPackage());
|
||||
|
||||
UWingServer::Printf(TEXT("Deleted widget '%s'\n"), *WidgetName);
|
||||
WingOut::Stdout.Printf(TEXT("Deleted widget '%s'\n"), *WidgetName);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
virtual void Handle() override
|
||||
{
|
||||
// Walk to the widget.
|
||||
WingFetcher F;
|
||||
WingFetcher F(WingOut::Stdout);
|
||||
UWidget* TargetWidget = F.Walk(Widget).Cast<UWidget>();
|
||||
if (!TargetWidget) return;
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
UWidgetBlueprint* BP = TargetWidget->GetTypedOuter<UWidgetBlueprint>();
|
||||
if (!BP)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Could not find owning WidgetBlueprint\n"));
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Could not find owning WidgetBlueprint\n"));
|
||||
return;
|
||||
}
|
||||
UWidgetTree* Tree = BP->WidgetTree;
|
||||
@@ -56,9 +56,9 @@ public:
|
||||
FString WidgetName = WingUtils::FormatName(TargetWidget);
|
||||
|
||||
// Find the new parent and verify it's a panel with room.
|
||||
UWidget* ParentWidget = WingUtils::FindOneWithExternalID(Parent, AllWidgets, TEXT("Widget"));
|
||||
UWidget* ParentWidget = WingUtils::FindOneWithExternalID(Parent, AllWidgets, TEXT("Widget"), WingOut::Stdout);
|
||||
if (!ParentWidget) return;
|
||||
if (!WingWidgets::CheckCanBeParent(ParentWidget)) return;
|
||||
if (!WingWidgets::CheckCanBeParent(ParentWidget, WingOut::Stdout)) return;
|
||||
UPanelWidget* ParentPanel = Cast<UPanelWidget>(ParentWidget);
|
||||
|
||||
// Check for circular reparenting.
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
{
|
||||
if (Ancestor == TargetWidget)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Cannot reparent '%s' under itself\n"), *WidgetName);
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Cannot reparent '%s' under itself\n"), *WidgetName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -77,6 +77,6 @@ public:
|
||||
// Add to new parent.
|
||||
ParentPanel->AddChild(TargetWidget);
|
||||
|
||||
UWingServer::Printf(TEXT("Reparented '%s' under '%s'\n"), *WidgetName, *Parent);
|
||||
WingOut::Stdout.Printf(TEXT("Reparented '%s' under '%s'\n"), *WidgetName, *Parent);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,16 +35,16 @@ public:
|
||||
TArray<WingWidgets::Type> Results = Widgets.Search(Query, MaxResults, false);
|
||||
for (const WingWidgets::Type& Entry : Results)
|
||||
{
|
||||
UWingServer::Printf(TEXT("%s\n"), *Entry.MenuName);
|
||||
WingOut::Stdout.Printf(TEXT("%s\n"), *Entry.MenuName);
|
||||
}
|
||||
|
||||
if (Results.Num() == 0)
|
||||
{
|
||||
UWingServer::Print(TEXT("No matching widget types found.\n"));
|
||||
WingOut::Stdout.Print(TEXT("No matching widget types found.\n"));
|
||||
}
|
||||
else if (Results.Num() >= MaxResults)
|
||||
{
|
||||
UWingServer::Printf(TEXT("WARNING: Reached limit of %d results. You may specify MaxResults.\n"), MaxResults);
|
||||
WingOut::Stdout.Printf(TEXT("WARNING: Reached limit of %d results. You may specify MaxResults.\n"), MaxResults);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -40,77 +40,77 @@ UWingComponentReference::FoundComponent UWingComponentReference::FindComponent(U
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool UWingComponentReference::CheckExists(UWingComponentReference::FoundComponent FC)
|
||||
bool UWingComponentReference::CheckExists(UWingComponentReference::FoundComponent FC, WingOut Errors)
|
||||
{
|
||||
if ((FC.SCS == nullptr) && (FC.Native == nullptr))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Cannot find component: %s\n"), *WingUtils::ExternalizeID(FC.Name));
|
||||
Errors.Printf(TEXT("Cannot find component: %s\n"), *WingUtils::ExternalizeID(FC.Name));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UWingComponentReference::CheckValidParent(UWingComponentReference::FoundComponent FC)
|
||||
bool UWingComponentReference::CheckValidParent(UWingComponentReference::FoundComponent FC, WingOut Errors)
|
||||
{
|
||||
if (FC.SCS && FC.Native)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Weirdness, two components named %s\n"),
|
||||
Errors.Printf(TEXT("Weirdness, two components named %s\n"),
|
||||
*WingUtils::ExternalizeID(FC.Name));
|
||||
return false;
|
||||
}
|
||||
if ((FC.SCS == nullptr) && (FC.Native == nullptr))
|
||||
{
|
||||
UWingServer::Printf(TEXT("No such parent component: %s\n"),
|
||||
Errors.Printf(TEXT("No such parent component: %s\n"),
|
||||
*WingUtils::ExternalizeID(FC.Name));
|
||||
return false;
|
||||
}
|
||||
if (FC.Native && (!Cast<USceneComponent>(FC.Native)))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Not a SceneComponent, so cannot be parent: %s\n"),
|
||||
Errors.Printf(TEXT("Not a SceneComponent, so cannot be parent: %s\n"),
|
||||
*WingUtils::ExternalizeID(FC.Name));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UWingComponentReference::CheckNoSuchComponent(FoundComponent FC)
|
||||
bool UWingComponentReference::CheckNoSuchComponent(FoundComponent FC, WingOut Errors)
|
||||
{
|
||||
if (FC.SCS || FC.Native)
|
||||
{
|
||||
UWingServer::Printf(TEXT("A component named %s already exists"),
|
||||
Errors.Printf(TEXT("A component named %s already exists"),
|
||||
*WingUtils::ExternalizeID(FC.Name));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UWingComponentReference::CheckNotNative(FoundComponent FC, const TCHAR *Action)
|
||||
bool UWingComponentReference::CheckNotNative(FoundComponent FC, const TCHAR *Action, WingOut Errors)
|
||||
{
|
||||
if (FC.Native != nullptr)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Component %s is native, cannot %s native components"),
|
||||
Errors.Printf(TEXT("Component %s is native, cannot %s native components"),
|
||||
*WingUtils::ExternalizeID(FC.Name), Action);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UWingComponentReference::CheckOwnedByBlueprint(FoundComponent FC, UBlueprint *BP)
|
||||
bool UWingComponentReference::CheckOwnedByBlueprint(FoundComponent FC, UBlueprint *BP, WingOut Errors)
|
||||
{
|
||||
if ((FC.SCS == nullptr) || (FC.SCS->GetSCS() != BP->SimpleConstructionScript))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Component %s belongs to blueprint %s, edit that blueprint instead"),
|
||||
Errors.Printf(TEXT("Component %s belongs to blueprint %s, edit that blueprint instead"),
|
||||
*WingUtils::ExternalizeID(FC.Name), *WingUtils::FormatName(FC.SCS->GetSCS()->GetBlueprint()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UWingComponentReference::CheckValidComponentClass(UClass *Class)
|
||||
bool UWingComponentReference::CheckValidComponentClass(UClass *Class, WingOut Errors)
|
||||
{
|
||||
if (!Class->IsChildOf(UActorComponent::StaticClass()))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Class does not derive from ActorComponent: %s\n"),
|
||||
Errors.Printf(TEXT("Class does not derive from ActorComponent: %s\n"),
|
||||
*WingUtils::FormatName(Class));
|
||||
return false;
|
||||
}
|
||||
@@ -139,26 +139,26 @@ void UWingComponentReference::AddChildNode(UBlueprint *BP, USCS_Node *NewNode, F
|
||||
}
|
||||
}
|
||||
|
||||
bool UWingComponentReference::AddComponent(UBlueprint *BP, UClass *Class, UWingComponentReference *Parent, FName Name)
|
||||
bool UWingComponentReference::AddComponent(UBlueprint *BP, UClass *Class, UWingComponentReference *Parent, FName Name, WingOut Errors)
|
||||
{
|
||||
TSet<FName> Names;
|
||||
FBlueprintEditorUtils::GetClassVariableList(BP, Names);
|
||||
if (Names.Contains(Name))
|
||||
{
|
||||
UWingServer::Printf(TEXT("There is already a variable or component named %s in %s.\n"),
|
||||
Errors.Printf(TEXT("There is already a variable or component named %s in %s.\n"),
|
||||
*WingUtils::ExternalizeID(Name), *WingUtils::FormatName(Class));
|
||||
return false;
|
||||
}
|
||||
FoundComponent ExistingComponent = FindComponent(BP, Name);
|
||||
if (!CheckNoSuchComponent(ExistingComponent)) return false;
|
||||
if (!CheckNoSuchComponent(ExistingComponent, Errors)) return false;
|
||||
FoundComponent ParentComponent = FindComponent(BP, Parent->VariableName);
|
||||
if (!CheckValidParent(ParentComponent)) return false;
|
||||
if (!CheckValidComponentClass(Class)) return false;
|
||||
if (!CheckValidParent(ParentComponent, Errors)) return false;
|
||||
if (!CheckValidComponentClass(Class, Errors)) return false;
|
||||
|
||||
USCS_Node *NewNode = BP->SimpleConstructionScript->CreateNode(Class, Name);
|
||||
if (NewNode == nullptr)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Could not create new component %s of class %s, unknown reason.\n"),
|
||||
Errors.Printf(TEXT("Could not create new component %s of class %s, unknown reason.\n"),
|
||||
*WingUtils::ExternalizeID(Name), *WingUtils::FormatName(Class));
|
||||
return false;
|
||||
}
|
||||
@@ -167,18 +167,18 @@ bool UWingComponentReference::AddComponent(UBlueprint *BP, UClass *Class, UWingC
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UWingComponentReference::ReparentComponent(UWingComponentReference *Parent)
|
||||
bool UWingComponentReference::ReparentComponent(UWingComponentReference *Parent, WingOut Errors)
|
||||
{
|
||||
FoundComponent ParentComponent = FindComponent(BP, Parent->VariableName);
|
||||
if (!CheckValidParent(ParentComponent)) return false;
|
||||
if (!CheckValidParent(ParentComponent, Errors)) return false;
|
||||
FoundComponent ThisComponent = FindComponent(BP, VariableName);
|
||||
if (!CheckExists(ThisComponent)) return false;
|
||||
if (!CheckNotNative(ThisComponent, TEXT("reparent"))) return false;
|
||||
if (!CheckOwnedByBlueprint(ThisComponent, BP)) return false;
|
||||
if (!CheckExists(ThisComponent, Errors)) return false;
|
||||
if (!CheckNotNative(ThisComponent, TEXT("reparent"), Errors)) return false;
|
||||
if (!CheckOwnedByBlueprint(ThisComponent, BP, Errors)) return false;
|
||||
|
||||
if (ParentComponent.SCS && ParentComponent.SCS->IsChildOf(ThisComponent.SCS))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Cannot parent a component to itself or its own child."));
|
||||
Errors.Printf(TEXT("Cannot parent a component to itself or its own child."));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -187,12 +187,12 @@ bool UWingComponentReference::ReparentComponent(UWingComponentReference *Parent)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UWingComponentReference::DeleteComponent()
|
||||
bool UWingComponentReference::DeleteComponent(WingOut Errors)
|
||||
{
|
||||
FoundComponent ThisComponent = FindComponent(BP, VariableName);
|
||||
if (!CheckExists(ThisComponent)) return false;
|
||||
if (!CheckNotNative(ThisComponent, TEXT("delete"))) return false;
|
||||
if (!CheckOwnedByBlueprint(ThisComponent, BP)) return false;
|
||||
if (!CheckExists(ThisComponent, Errors)) return false;
|
||||
if (!CheckNotNative(ThisComponent, TEXT("delete"), Errors)) return false;
|
||||
if (!CheckOwnedByBlueprint(ThisComponent, BP, Errors)) return false;
|
||||
BP->SimpleConstructionScript->RemoveNodeAndPromoteChildren(ThisComponent.SCS);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5,26 +5,26 @@
|
||||
#include "AssetRegistry/AssetRegistryModule.h"
|
||||
#include "Kismet2/EnumEditorUtils.h"
|
||||
|
||||
bool WingFactories::CheckNewAssetPath(const FString& Path)
|
||||
bool WingFactories::CheckNewAssetPath(const FString& Path, WingOut Errors)
|
||||
{
|
||||
if (UPackageTools::SanitizePackageName(Path) != Path)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Package path '%s' is not a valid package name\n"), *Path);
|
||||
Errors.Printf(TEXT("ERROR: Package path '%s' is not a valid package name\n"), *Path);
|
||||
return false;
|
||||
}
|
||||
if (!FPackageName::IsValidTextForLongPackageName(Path))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Package path '%s' is not a valid package name\n"), *Path);
|
||||
Errors.Printf(TEXT("ERROR: Package path '%s' is not a valid package name\n"), *Path);
|
||||
return false;
|
||||
}
|
||||
if (!Path.StartsWith(TEXT("/Game")))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Package path '%s' must start with '/Game'\n"), *Path);
|
||||
Errors.Printf(TEXT("ERROR: Package path '%s' must start with '/Game'\n"), *Path);
|
||||
return false;
|
||||
}
|
||||
if (FindObject<UPackage>(nullptr, *Path))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: An asset already exists at '%s'\n"), *Path);
|
||||
Errors.Printf(TEXT("ERROR: An asset already exists at '%s'\n"), *Path);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -38,24 +38,24 @@ bool WingFactories::IsBlacklisted(UClass* FactoryClass)
|
||||
return false;
|
||||
}
|
||||
|
||||
UObject* WingFactories::CreateAsset(const FString& Path, UFactory* Factory)
|
||||
UObject* WingFactories::CreateAsset(const FString& Path, UFactory* Factory, WingOut Errors)
|
||||
{
|
||||
// Check the blacklist.
|
||||
if (IsBlacklisted(Factory->GetClass()))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Factory '%s' is blacklisted\n"), *Factory->GetClass()->GetName());
|
||||
Errors.Printf(TEXT("ERROR: Factory '%s' is blacklisted\n"), *Factory->GetClass()->GetName());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Validate the path, and that there's not already something there.
|
||||
if (!CheckNewAssetPath(Path)) return nullptr;
|
||||
if (!CheckNewAssetPath(Path, Errors)) return nullptr;
|
||||
FName Name = FName(FPackageName::GetShortName(Path));
|
||||
|
||||
// Create the package.
|
||||
UPackage *Package = CreatePackage(*Path);
|
||||
if (!Package)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to create package at '%s'\n"), *Path);
|
||||
Errors.Printf(TEXT("ERROR: Failed to create package at '%s'\n"), *Path);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ UObject* WingFactories::CreateAsset(const FString& Path, UFactory* Factory)
|
||||
}
|
||||
else
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Factory '%s' failed to create an object\n"), *Factory->GetClass()->GetName());
|
||||
Errors.Printf(TEXT("ERROR: Factory '%s' failed to create an object\n"), *Factory->GetClass()->GetName());
|
||||
Package->ClearDirtyFlag();
|
||||
Package->MarkAsGarbage();
|
||||
return nullptr;
|
||||
@@ -109,7 +109,7 @@ UObject* UEnumFactoryWing::FactoryCreateNew(UClass* Class, UObject* InParent, FN
|
||||
{
|
||||
if (!FEnumEditorUtils::IsNameAvailebleForUserDefinedEnum(Name))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Enum name is already taken: %s\n"), *Name.ToString());
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Enum name is already taken: %s\n"), *Name.ToString());
|
||||
return nullptr;
|
||||
}
|
||||
return FEnumEditorUtils::CreateUserDefinedEnum(InParent, Name, Flags);
|
||||
|
||||
@@ -59,11 +59,11 @@ WingFetcher& WingFetcher::SetError()
|
||||
void WingFetcher::PathFailed(const TCHAR* Expected)
|
||||
{
|
||||
if (ResultPin)
|
||||
UWingServer::Printf(TEXT("ERROR: Path specifies a pin, but expected %s\n"), Expected);
|
||||
Errors.Printf(TEXT("ERROR: Path specifies a pin, but expected %s\n"), Expected);
|
||||
else if (Obj)
|
||||
UWingServer::Printf(TEXT("ERROR: Path specifies a %s, but expected %s\n"), *Obj->GetClass()->GetName(), Expected);
|
||||
Errors.Printf(TEXT("ERROR: Path specifies a %s, but expected %s\n"), *Obj->GetClass()->GetName(), Expected);
|
||||
else
|
||||
UWingServer::Printf(TEXT("ERROR: Path led to a null pointer\n"));
|
||||
Errors.Printf(TEXT("ERROR: Path led to a null pointer\n"));
|
||||
UWingServer::SuggestManual(WingManual::Section::Paths);
|
||||
SetError();
|
||||
}
|
||||
@@ -71,11 +71,11 @@ void WingFetcher::PathFailed(const TCHAR* Expected)
|
||||
WingFetcher& WingFetcher::TypeMismatch(const TCHAR* Walker, const TCHAR* Expected)
|
||||
{
|
||||
if (ResultPin)
|
||||
UWingServer::Printf(TEXT("ERROR: Input to '%s' is a pin, but expected %s\n"), Walker, Expected);
|
||||
Errors.Printf(TEXT("ERROR: Input to '%s' is a pin, but expected %s\n"), Walker, Expected);
|
||||
else if (Obj)
|
||||
UWingServer::Printf(TEXT("ERROR: Input to '%s' is %s, but expected %s\n"), Walker, *Obj->GetClass()->GetName(), Expected);
|
||||
Errors.Printf(TEXT("ERROR: Input to '%s' is %s, but expected %s\n"), Walker, *Obj->GetClass()->GetName(), Expected);
|
||||
else
|
||||
UWingServer::Printf(TEXT("ERROR: Path led to a null pointer\n"));
|
||||
Errors.Printf(TEXT("ERROR: Path led to a null pointer\n"));
|
||||
UWingServer::SuggestManual(WingManual::Section::Paths);
|
||||
SetError();
|
||||
return *this;
|
||||
@@ -87,7 +87,7 @@ WingFetcher& WingFetcher::Walk(const FString& Path)
|
||||
|
||||
if (Path.Contains(TEXT(" ")))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Paths may not contain whitespace."));
|
||||
Errors.Printf(TEXT("ERROR: Paths may not contain whitespace."));
|
||||
UWingServer::SuggestManual(WingManual::Section::Paths);
|
||||
UWingServer::SuggestManual(WingManual::Section::EscapeSequences);
|
||||
return SetError();
|
||||
@@ -96,7 +96,7 @@ WingFetcher& WingFetcher::Walk(const FString& Path)
|
||||
Path.ParseIntoArray(Segments, TEXT(","));
|
||||
if (Segments.Num() == 0)
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Empty path\n"));
|
||||
Errors.Print(TEXT("ERROR: Empty path\n"));
|
||||
UWingServer::SuggestManual(WingManual::Section::Paths);
|
||||
return SetError();
|
||||
}
|
||||
@@ -117,7 +117,7 @@ WingFetcher& WingFetcher::Walk(const FString& Path)
|
||||
WalkFunc Func = GetWalker(Key);
|
||||
if (!Func)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Unknown path step '%s'\n"), *Key);
|
||||
Errors.Printf(TEXT("ERROR: Unknown path step '%s'\n"), *Key);
|
||||
UWingServer::SuggestManual(WingManual::Section::Paths);
|
||||
return SetError();
|
||||
}
|
||||
@@ -134,7 +134,7 @@ WingFetcher& WingFetcher::Asset(const FString& PackagePath)
|
||||
|
||||
if (!PackagePath.StartsWith(TEXT("/")))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Path must start with '/', got '%s'\n"), *PackagePath);
|
||||
Errors.Printf(TEXT("ERROR: Path must start with '/', got '%s'\n"), *PackagePath);
|
||||
UWingServer::SuggestManual(WingManual::Section::Paths);
|
||||
return SetError();
|
||||
}
|
||||
@@ -144,13 +144,13 @@ WingFetcher& WingFetcher::Asset(const FString& PackagePath)
|
||||
FString PackageName = FPackageName::ObjectPathToPackageName(PackagePath);
|
||||
if (!FPackageName::DoesPackageExist(PackageName))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Asset '%s' does not exist.\n"), *PackagePath);
|
||||
Errors.Printf(TEXT("ERROR: Asset '%s' does not exist.\n"), *PackagePath);
|
||||
return SetError();
|
||||
}
|
||||
SetObj(LoadObject<UObject>(nullptr, *PackagePath));
|
||||
if (!Obj)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Could not load asset '%s'\n"), *PackagePath);
|
||||
Errors.Printf(TEXT("ERROR: Could not load asset '%s'\n"), *PackagePath);
|
||||
return SetError();
|
||||
}
|
||||
|
||||
@@ -160,13 +160,13 @@ WingFetcher& WingFetcher::Asset(const FString& PackagePath)
|
||||
UAssetEditorSubsystem* Sub = GEditor->GetEditorSubsystem<UAssetEditorSubsystem>();
|
||||
if (!Sub || !Sub->OpenEditorForAsset(Obj))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Could not open editor for '%s'\n"), *PackagePath);
|
||||
Errors.Printf(TEXT("ERROR: Could not open editor for '%s'\n"), *PackagePath);
|
||||
return SetError();
|
||||
}
|
||||
Editor = Sub->FindEditorForAsset(OriginalAsset, false);
|
||||
if (!Editor)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Could not find editor instance for '%s'\n"), *PackagePath);
|
||||
Errors.Printf(TEXT("ERROR: Could not find editor instance for '%s'\n"), *PackagePath);
|
||||
return SetError();
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ bool WingFetcher::CheckAssetIsA(UClass* StaticClass)
|
||||
if (bError) return false;
|
||||
if (!OriginalAsset || !OriginalAsset->IsA(StaticClass))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Asset is %s, expected %s\n"),
|
||||
Errors.Printf(TEXT("ERROR: Asset is %s, expected %s\n"),
|
||||
OriginalAsset ? *OriginalAsset->GetClass()->GetName() : TEXT("null"),
|
||||
*StaticClass->GetName());
|
||||
SetError();
|
||||
@@ -202,14 +202,14 @@ WingFetcher& WingFetcher::Graph(const FString& Value)
|
||||
{
|
||||
if (!Value.IsEmpty())
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Materials have only one graph, with a blank name.\n\n"));
|
||||
Errors.Printf(TEXT("ERROR: Materials have only one graph, with a blank name.\n\n"));
|
||||
UWingServer::SuggestManual(WingManual::Section::Paths);
|
||||
return SetError();
|
||||
}
|
||||
WingUtils::EnsureMaterialGraph(Mat);
|
||||
if (!Mat->MaterialGraph)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Material '%s' has no material graph\n"), *Mat->GetName());
|
||||
Errors.Printf(TEXT("ERROR: Material '%s' has no material graph\n"), *Mat->GetName());
|
||||
return SetError();
|
||||
}
|
||||
SetObj(Mat->MaterialGraph);
|
||||
@@ -224,13 +224,13 @@ WingFetcher& WingFetcher::Graph(const FString& Value)
|
||||
}
|
||||
|
||||
TArray<UEdGraph*> Graphs = WingUtils::AllGraphs(BP);
|
||||
UEdGraph* Found = WingUtils::FindOneWithExternalID(Value, Graphs, TEXT("graph"));
|
||||
UEdGraph* Found = WingUtils::FindOneWithExternalID(Value, Graphs, TEXT("graph"), Errors);
|
||||
if (!Found)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Graphs that exist in blueprint:\n"));
|
||||
Errors.Printf(TEXT("Graphs that exist in blueprint:\n"));
|
||||
for (const UEdGraph *G : Graphs)
|
||||
{
|
||||
UWingServer::Printf(TEXT(" %s\n"), *WingUtils::FormatName(G));
|
||||
Errors.Printf(TEXT(" %s\n"), *WingUtils::FormatName(G));
|
||||
}
|
||||
return SetError();
|
||||
}
|
||||
@@ -253,13 +253,13 @@ WingFetcher& WingFetcher::Node(const FString& Value)
|
||||
|
||||
// Get the nodes from the graph.
|
||||
TArray<UEdGraphNode *> AllNodes = WingUtils::AllNodes(Graph);
|
||||
UEdGraphNode *Node = WingUtils::FindOneWithExternalID(Value, AllNodes, TEXT("node"));
|
||||
UEdGraphNode *Node = WingUtils::FindOneWithExternalID(Value, AllNodes, TEXT("node"), Errors);
|
||||
if (Node == nullptr)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Nodes that exist in graph:\n"));
|
||||
Errors.Printf(TEXT("Nodes that exist in graph:\n"));
|
||||
for (const UEdGraphNode *N : AllNodes)
|
||||
{
|
||||
UWingServer::Printf(TEXT(" %s\n"), *WingUtils::FormatName(N));
|
||||
Errors.Printf(TEXT(" %s\n"), *WingUtils::FormatName(N));
|
||||
}
|
||||
return SetError();
|
||||
}
|
||||
@@ -277,13 +277,13 @@ WingFetcher& WingFetcher::Pin(const FString& Value)
|
||||
TypeMismatch(TEXT("pin"), TEXT("node"));
|
||||
return SetError();
|
||||
}
|
||||
UEdGraphPin *Found = WingUtils::FindOneWithExternalID(Value, N->Pins, TEXT("pin"));
|
||||
UEdGraphPin *Found = WingUtils::FindOneWithExternalID(Value, N->Pins, TEXT("pin"), Errors);
|
||||
if (!Found)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Pins that exist in the node:\n"));
|
||||
Errors.Printf(TEXT("Pins that exist in the node:\n"));
|
||||
for (const UEdGraphPin *P : N->Pins)
|
||||
{
|
||||
UWingServer::Printf(TEXT(" %s\n"), *WingUtils::FormatName(P));
|
||||
Errors.Printf(TEXT(" %s\n"), *WingUtils::FormatName(P));
|
||||
}
|
||||
return SetError();
|
||||
}
|
||||
@@ -303,13 +303,13 @@ WingFetcher& WingFetcher::Component(const FString& Value)
|
||||
}
|
||||
|
||||
TArray<UWingComponentReference*> AllComponents = UWingComponentReference::GetAll(BP);
|
||||
UWingComponentReference* Found = WingUtils::FindOneWithExternalID(Value, AllComponents, TEXT("component"));
|
||||
UWingComponentReference* Found = WingUtils::FindOneWithExternalID(Value, AllComponents, TEXT("component"), Errors);
|
||||
if (!Found)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Components that exist in the blueprint:\n"));
|
||||
Errors.Printf(TEXT("Components that exist in the blueprint:\n"));
|
||||
for (const UWingComponentReference* C : AllComponents)
|
||||
{
|
||||
UWingServer::Printf(TEXT(" %s\n"), *WingUtils::FormatName(C));
|
||||
Errors.Printf(TEXT(" %s\n"), *WingUtils::FormatName(C));
|
||||
}
|
||||
return SetError();
|
||||
}
|
||||
@@ -331,13 +331,13 @@ WingFetcher& WingFetcher::Widget(const FString& Value)
|
||||
|
||||
TArray<UWidget*> AllWidgets;
|
||||
WidgetBP->WidgetTree->GetAllWidgets(AllWidgets);
|
||||
UWidget* Found = WingUtils::FindOneWithExternalID(Value, AllWidgets, TEXT("widget"));
|
||||
UWidget* Found = WingUtils::FindOneWithExternalID(Value, AllWidgets, TEXT("widget"), Errors);
|
||||
if (!Found)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Widgets that exist in the blueprint:\n"));
|
||||
Errors.Printf(TEXT("Widgets that exist in the blueprint:\n"));
|
||||
for (const UWidget *W : AllWidgets)
|
||||
{
|
||||
UWingServer::Printf(TEXT(" %s\n"), *WingUtils::FormatName(W));
|
||||
Errors.Printf(TEXT(" %s\n"), *WingUtils::FormatName(W));
|
||||
}
|
||||
return SetError();
|
||||
}
|
||||
@@ -358,18 +358,17 @@ WingFetcher& WingFetcher::LevelBlueprint(const FString& Value)
|
||||
|
||||
if (!World->PersistentLevel)
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: World has no PersistentLevel\n"));
|
||||
Errors.Print(TEXT("ERROR: World has no PersistentLevel\n"));
|
||||
return SetError();
|
||||
}
|
||||
|
||||
ULevelScriptBlueprint* LevelBP = World->PersistentLevel->GetLevelScriptBlueprint(true);
|
||||
if (!LevelBP)
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: World has no level blueprint\n"));
|
||||
Errors.Print(TEXT("ERROR: World has no level blueprint\n"));
|
||||
return SetError();
|
||||
}
|
||||
|
||||
SetObj(LevelBP);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ void WingGraphExport::EmitNodeProperties(UEdGraphNode* Node, FStringBuilderBase&
|
||||
FString PrimaryCategory;
|
||||
if (UMaterialGraphNode* MatNode = Cast<UMaterialGraphNode>(Node))
|
||||
{
|
||||
WingPropHandle::Handles Handles = Props.GetDetails(Node, false);
|
||||
WingPropHandle::Handles Handles = Props.GetDetails(Node, false, WingOut::Stdout);
|
||||
PrimaryCategory = MatNode->MaterialExpression->GetClass()->GetName();
|
||||
for (const TSharedPtr<IPropertyHandle>& H : Handles)
|
||||
{
|
||||
@@ -265,7 +265,7 @@ void WingGraphExport::EmitNodeProperties(UEdGraphNode* Node, FStringBuilderBase&
|
||||
}
|
||||
else if (bPrimary)
|
||||
{
|
||||
WingPropHandle::Handles Handles = Props.GetDetails(Node, false);
|
||||
WingPropHandle::Handles Handles = Props.GetDetails(Node, false, WingOut::Stdout);
|
||||
for (const TSharedPtr<IPropertyHandle>& H : Handles)
|
||||
WingPropHandle::Print(*H, Out);
|
||||
}
|
||||
@@ -274,8 +274,8 @@ void WingGraphExport::EmitNodeProperties(UEdGraphNode* Node, FStringBuilderBase&
|
||||
void WingGraphExport::EmitLocalVariables()
|
||||
{
|
||||
WingVariables Vars;
|
||||
Vars.SetBackingStore(Graph);
|
||||
Vars.Load();
|
||||
Vars.SetBackingStore(Graph, WingOut::Stdout);
|
||||
Vars.Load(WingOut::Stdout);
|
||||
Vars.Print(Output);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
|
||||
void WingManual::PrintHandlerPrototype(const FWingHandlerConfig& Handler)
|
||||
{
|
||||
UWingServer::Print(Handler.Name);
|
||||
UWingServer::Print(TEXT("("));
|
||||
WingOut::Stdout.Print(Handler.Name);
|
||||
WingOut::Stdout.Print(TEXT("("));
|
||||
bool bFirst = true;
|
||||
for (TFieldIterator<FProperty> PropIt(Handler.Class.Get(), EFieldIterationFlags::None); PropIt; ++PropIt)
|
||||
{
|
||||
if (!bFirst) UWingServer::Print(TEXT(","));
|
||||
if (!bFirst) WingOut::Stdout.Print(TEXT(","));
|
||||
bFirst = false;
|
||||
if (PropIt->HasMetaData(TEXT("Optional"))) UWingServer::Print(TEXT("?"));
|
||||
UWingServer::Print(PropIt->GetName());
|
||||
if (PropIt->HasMetaData(TEXT("Optional"))) WingOut::Stdout.Print(TEXT("?"));
|
||||
WingOut::Stdout.Print(PropIt->GetName());
|
||||
}
|
||||
UWingServer::Print(TEXT(")\n"));
|
||||
WingOut::Stdout.Print(TEXT(")\n"));
|
||||
}
|
||||
|
||||
void WingManual::PrintHandlerArguments(const FWingHandlerConfig& Handler)
|
||||
@@ -31,30 +31,30 @@ void WingManual::PrintHandlerArguments(const FWingHandlerConfig& Handler)
|
||||
|
||||
if (bOptional)
|
||||
{
|
||||
UWingServer::Printf(TEXT(" %s (optional %s)"), *Name, *Type);
|
||||
WingOut::Stdout.Printf(TEXT(" %s (optional %s)"), *Name, *Type);
|
||||
}
|
||||
else
|
||||
{
|
||||
UWingServer::Printf(TEXT(" %s (%s)"), *Name, *Type);
|
||||
WingOut::Stdout.Printf(TEXT(" %s (%s)"), *Name, *Type);
|
||||
}
|
||||
if (!Desc.IsEmpty()) UWingServer::Printf(TEXT(" — %s"), *Desc);
|
||||
UWingServer::Print(TEXT("\n"));
|
||||
if (!Desc.IsEmpty()) WingOut::Stdout.Printf(TEXT(" — %s"), *Desc);
|
||||
WingOut::Stdout.Print(TEXT("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
void WingManual::PrintHandlerDescription(const FWingHandlerConfig& Handler)
|
||||
{
|
||||
if (Handler.Documentation.IsEmpty()) return;
|
||||
UWingServer::Print(WingUtils::WrapText(Handler.Documentation, 80, TEXT(" // ")));
|
||||
WingOut::Stdout.Print(WingUtils::WrapText(Handler.Documentation, 80, TEXT(" // ")));
|
||||
}
|
||||
|
||||
void WingManual::PrintHandlerHelp(const FWingHandlerConfig& Handler)
|
||||
{
|
||||
UWingServer::Print(TEXT("\n"));
|
||||
WingOut::Stdout.Print(TEXT("\n"));
|
||||
PrintHandlerPrototype(Handler);
|
||||
PrintHandlerArguments(Handler);
|
||||
PrintHandlerDescription(Handler);
|
||||
UWingServer::Print(TEXT("\n"));
|
||||
WingOut::Stdout.Print(TEXT("\n"));
|
||||
}
|
||||
|
||||
void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* Handler, bool Abridged)
|
||||
@@ -65,7 +65,7 @@ void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* H
|
||||
|
||||
if (Abridged)
|
||||
{
|
||||
UWingServer::Printf(TEXT("\n--- AUTOMATIC DOCUMENTATION ---\n"));
|
||||
WingOut::Stdout.Printf(TEXT("\n--- AUTOMATIC DOCUMENTATION ---\n"));
|
||||
}
|
||||
|
||||
if (Handler && (Sections.Contains(Section::HandlerHelp) || bPrintAll))
|
||||
@@ -77,7 +77,7 @@ void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* H
|
||||
{
|
||||
if (Abridged)
|
||||
{
|
||||
UWingServer::Print(TEXT(
|
||||
WingOut::Stdout.Print(TEXT(
|
||||
"\n PATHS: Here are some example paths:"
|
||||
"\n /Game/Widgets/WB_Hotkeys,widget:Canvas·122"
|
||||
"\n /Game/Testing/BP_Test,graph:Rescale·Actor,node:K2Node_CallFunction_0,pin:Scale"
|
||||
@@ -87,7 +87,7 @@ void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* H
|
||||
}
|
||||
else
|
||||
{
|
||||
UWingServer::Print(TEXT(
|
||||
WingOut::Stdout.Print(TEXT(
|
||||
"\n PATHS:"
|
||||
"\n"
|
||||
"\n Most commands require you to specify a path. A path starts"
|
||||
@@ -123,7 +123,7 @@ void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* H
|
||||
{
|
||||
if (Abridged)
|
||||
{
|
||||
UWingServer::Print(TEXT(
|
||||
WingOut::Stdout.Print(TEXT(
|
||||
"\n TYPES: Here are some examples of valid types:"
|
||||
"\n Bool, String, Vector, Rotator, HitResult, Actor, Character,"
|
||||
"\n PlayerController, EBlendMode, EMovementMode, BP_Manny, BP_Quinn,"
|
||||
@@ -134,7 +134,7 @@ void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* H
|
||||
}
|
||||
else
|
||||
{
|
||||
UWingServer::Print(TEXT(
|
||||
WingOut::Stdout.Print(TEXT(
|
||||
"\n TYPES:"
|
||||
"\n"
|
||||
"\n To change variable types, or to express function prototypes, you will"
|
||||
@@ -157,7 +157,7 @@ void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* H
|
||||
{
|
||||
if (Abridged)
|
||||
{
|
||||
UWingServer::Print(TEXT(
|
||||
WingOut::Stdout.Print(TEXT(
|
||||
"\n VARIABLE DECLARATIONS: example variable declarations:"
|
||||
"\n Array<Actor> Actors"
|
||||
"\n Float F (InstanceEditable)"
|
||||
@@ -166,7 +166,7 @@ void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* H
|
||||
}
|
||||
else
|
||||
{
|
||||
UWingServer::Print(TEXT(
|
||||
WingOut::Stdout.Print(TEXT(
|
||||
"\n VARIABLE DECLARATIONS:"
|
||||
"\n"
|
||||
"\n We have our own syntax for variable declarations: a type,"
|
||||
@@ -192,7 +192,7 @@ void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* H
|
||||
{
|
||||
if (Abridged)
|
||||
{
|
||||
UWingServer::Print(TEXT(
|
||||
WingOut::Stdout.Print(TEXT(
|
||||
"\n USING HTML ESCAPE SEQUENCES:"
|
||||
"\n When we output FNames, we use HTML escape sequences for the"
|
||||
"\n following marks: \\\"'(),.:;<=>& We also escape control"
|
||||
@@ -218,7 +218,7 @@ void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* H
|
||||
}
|
||||
else
|
||||
{
|
||||
UWingServer::Print(TEXT(
|
||||
WingOut::Stdout.Print(TEXT(
|
||||
"\n USING HTML ESCAPE SEQUENCES:"
|
||||
"\n When we output FNames, we use HTML escape sequences for the"
|
||||
"\n following marks: \\\"'(),.:;<=>&, and for certain other characters."
|
||||
@@ -234,7 +234,7 @@ void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* H
|
||||
|
||||
if (Sections.Contains(Section::Whitespace) || bPrintAll)
|
||||
{
|
||||
UWingServer::Print(TEXT(
|
||||
WingOut::Stdout.Print(TEXT(
|
||||
"\n ABOUT WHITESPACE:"
|
||||
"\n Do not put excess whitespace into paths, typenames, or"
|
||||
"\n function prototypes, only use whitespace where it is required"
|
||||
@@ -247,7 +247,7 @@ void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* H
|
||||
{
|
||||
if (Abridged)
|
||||
{
|
||||
UWingServer::Print(TEXT(
|
||||
WingOut::Stdout.Print(TEXT(
|
||||
"\n MATERIAL EDITING:"
|
||||
"\n We do not expose material expressions directly. Instead, use"
|
||||
"\n Property_Dump and Property_Set on the material graph nodes to"
|
||||
@@ -257,7 +257,7 @@ void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* H
|
||||
}
|
||||
else
|
||||
{
|
||||
UWingServer::Print(TEXT(
|
||||
WingOut::Stdout.Print(TEXT(
|
||||
"\n MATERIAL EDITING:"
|
||||
"\n"
|
||||
"\n We do not expose material expressions directly. Instead, you"
|
||||
@@ -272,7 +272,7 @@ void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* H
|
||||
|
||||
if (Sections.Contains(Section::ImportantCommands) || bPrintAll)
|
||||
{
|
||||
UWingServer::Print(TEXT(
|
||||
WingOut::Stdout.Print(TEXT(
|
||||
"\n COMMANDS YOU SHOULD KNOW ABOUT AND REMEMBER:"
|
||||
"\n UserManual: this explanation"
|
||||
"\n ShowCommands: a full list of all the commands"
|
||||
@@ -288,6 +288,6 @@ void WingManual::PrintManual(TSet<Section> Sections, const FWingHandlerConfig* H
|
||||
|
||||
if (Abridged)
|
||||
{
|
||||
UWingServer::Printf(TEXT("\nUse command 'UserManual' to see the full manual.\n"));
|
||||
WingOut::Stdout.Printf(TEXT("\nUse command 'UserManual' to see the full manual.\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ TMap<FMaterialParameterInfo, FMaterialParameterMetadata> WingMaterialParameter::
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool WingMaterialParameter::ParseMaterialParameterAssociation(const FString& Str, EMaterialParameterAssociation& OutAssociation)
|
||||
bool WingMaterialParameter::ParseMaterialParameterAssociation(const FString& Str, EMaterialParameterAssociation& OutAssociation, WingOut Errors)
|
||||
{
|
||||
if (Str.Equals(TEXT("Global"), ESearchCase::IgnoreCase))
|
||||
OutAssociation = GlobalParameter;
|
||||
@@ -25,7 +25,7 @@ bool WingMaterialParameter::ParseMaterialParameterAssociation(const FString& Str
|
||||
OutAssociation = BlendParameter;
|
||||
else
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Invalid ParameterAssociation '%s' (expected 'Global', 'Layer', or 'Blend')\n"), *Str);
|
||||
Errors.Printf(TEXT("ERROR: Invalid ParameterAssociation '%s' (expected 'Global', 'Layer', or 'Blend')\n"), *Str);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -43,35 +43,35 @@ void WingMaterialParameter::FormatMaterialParameter(const FMaterialParameterInfo
|
||||
switch (Meta.Value.Type)
|
||||
{
|
||||
case EMaterialParameterType::Scalar:
|
||||
UWingServer::Printf(TEXT(" %sScalar \"%s\" = %g\n"), *Prefix, *Info.Name.ToString(), Meta.Value.AsScalar());
|
||||
WingOut::Stdout.Printf(TEXT(" %sScalar \"%s\" = %g\n"), *Prefix, *Info.Name.ToString(), Meta.Value.AsScalar());
|
||||
break;
|
||||
case EMaterialParameterType::Vector:
|
||||
{
|
||||
FLinearColor C = Meta.Value.AsLinearColor();
|
||||
UWingServer::Printf(TEXT(" %sVector \"%s\" = (R=%.3f, G=%.3f, B=%.3f, A=%.3f)\n"),
|
||||
WingOut::Stdout.Printf(TEXT(" %sVector \"%s\" = (R=%.3f, G=%.3f, B=%.3f, A=%.3f)\n"),
|
||||
*Prefix, *Info.Name.ToString(), C.R, C.G, C.B, C.A);
|
||||
break;
|
||||
}
|
||||
case EMaterialParameterType::DoubleVector:
|
||||
{
|
||||
FVector4d V = Meta.Value.AsVector4d();
|
||||
UWingServer::Printf(TEXT(" %sDoubleVector \"%s\" = (%.3f, %.3f, %.3f, %.3f)\n"),
|
||||
WingOut::Stdout.Printf(TEXT(" %sDoubleVector \"%s\" = (%.3f, %.3f, %.3f, %.3f)\n"),
|
||||
*Prefix, *Info.Name.ToString(), V.X, V.Y, V.Z, V.W);
|
||||
break;
|
||||
}
|
||||
case EMaterialParameterType::Texture:
|
||||
{
|
||||
UTexture* Tex = Cast<UTexture>(Meta.Value.AsTextureObject());
|
||||
UWingServer::Printf(TEXT(" %sTexture \"%s\" = %s\n"),
|
||||
WingOut::Stdout.Printf(TEXT(" %sTexture \"%s\" = %s\n"),
|
||||
*Prefix, *Info.Name.ToString(), Tex ? *WingUtils::FormatName(Tex) : TEXT("None"));
|
||||
break;
|
||||
}
|
||||
case EMaterialParameterType::StaticSwitch:
|
||||
UWingServer::Printf(TEXT(" %sStaticSwitch \"%s\" = %s\n"),
|
||||
WingOut::Stdout.Printf(TEXT(" %sStaticSwitch \"%s\" = %s\n"),
|
||||
*Prefix, *Info.Name.ToString(), Meta.Value.AsStaticSwitch() ? TEXT("true") : TEXT("false"));
|
||||
break;
|
||||
default:
|
||||
UWingServer::Printf(TEXT(" %sType%d \"%s\"\n"), *Prefix, (int)Meta.Value.Type, *Info.Name.ToString());
|
||||
WingOut::Stdout.Printf(TEXT(" %sType%d \"%s\"\n"), *Prefix, (int)Meta.Value.Type, *Info.Name.ToString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,19 +186,19 @@ TSharedPtr<IPropertyHandle> WingPropHandle::TryNamedProperty(const UStruct* Scri
|
||||
return TryNamedProperty(GetRootForStruct(ScriptStruct, Data), Name, RootFilter);
|
||||
}
|
||||
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(UObject* Obj, FName Name, bool RootFilter)
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(UObject* Obj, FName Name, bool RootFilter, WingOut Errors)
|
||||
{
|
||||
TSharedPtr<IPropertyHandle> Result = TryNamedProperty(Obj, Name, RootFilter);
|
||||
if (!Result)
|
||||
UWingServer::Printf(TEXT("ERROR: Property '%s' not found\n"), *Name.ToString());
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' not found\n"), *Name.ToString());
|
||||
return Result;
|
||||
}
|
||||
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(const UStruct* ScriptStruct, uint8* Data, FName Name, bool RootFilter)
|
||||
TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(const UStruct* ScriptStruct, uint8* Data, FName Name, bool RootFilter, WingOut Errors)
|
||||
{
|
||||
TSharedPtr<IPropertyHandle> Result = TryNamedProperty(ScriptStruct, Data, Name, RootFilter);
|
||||
if (!Result)
|
||||
UWingServer::Printf(TEXT("ERROR: Property '%s' not found\n"), *Name.ToString());
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' not found\n"), *Name.ToString());
|
||||
return Result;
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ TSharedPtr<IPropertyHandle> WingPropHandle::NamedProperty(const UStruct* ScriptS
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
WingPropHandle::Handles WingPropHandle::GetDetails(UObject* Obj, bool Mutable)
|
||||
WingPropHandle::Handles WingPropHandle::GetDetails(UObject* Obj, bool Mutable, WingOut Errors)
|
||||
{
|
||||
bool RootFilter = false;
|
||||
|
||||
@@ -219,7 +219,7 @@ WingPropHandle::Handles WingPropHandle::GetDetails(UObject* Obj, bool Mutable)
|
||||
{
|
||||
if (!BP->GeneratedClass)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Blueprint '%s' has no GeneratedClass\n"), *Obj->GetName());
|
||||
Errors.Printf(TEXT("ERROR: Blueprint '%s' has no GeneratedClass\n"), *Obj->GetName());
|
||||
return {};
|
||||
}
|
||||
Obj = BP->GeneratedClass->GetDefaultObject();
|
||||
@@ -235,7 +235,7 @@ WingPropHandle::Handles WingPropHandle::GetDetails(UObject* Obj, bool Mutable)
|
||||
Obj = Mutable ? Ref->GetMutableTemplate() : Ref->GetImmutableTemplate();
|
||||
if (!Obj)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Component '%s' has no template\n"), *Ref->VariableName.ToString());
|
||||
Errors.Printf(TEXT("ERROR: Component '%s' has no template\n"), *Ref->VariableName.ToString());
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -277,7 +277,7 @@ WingPropHandle::Handles WingPropHandle::GetDetails(UObject* Obj, bool Mutable)
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool WingPropHandle::OrganizeByName(const Handles &HList, TMap<FName, TSharedPtr<IPropertyHandle>> &Result)
|
||||
bool WingPropHandle::OrganizeByName(const Handles &HList, TMap<FName, TSharedPtr<IPropertyHandle>> &Result, WingOut Errors)
|
||||
{
|
||||
Result.Empty();
|
||||
TSet<FName> DuplicateNames;
|
||||
@@ -288,12 +288,12 @@ bool WingPropHandle::OrganizeByName(const Handles &HList, TMap<FName, TSharedPtr
|
||||
else Result.Add(Name, H);
|
||||
}
|
||||
if (DuplicateNames.IsEmpty()) return true;
|
||||
UWingServer::Print(TEXT("More than one property with name:"));
|
||||
Errors.Print(TEXT("More than one property with name:"));
|
||||
for (FName DupName : DuplicateNames)
|
||||
{
|
||||
UWingServer::Printf(TEXT(" %s"), *WingUtils::ExternalizeID(DupName));
|
||||
Errors.Printf(TEXT(" %s"), *WingUtils::ExternalizeID(DupName));
|
||||
}
|
||||
UWingServer::Print(TEXT("\n"));
|
||||
Errors.Print(TEXT("\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ FString WingPropHandle::GetText(IPropertyHandle& Handle)
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool WingPropHandle::SetText(IPropertyHandle& Handle, const FString& Text)
|
||||
bool WingPropHandle::SetText(IPropertyHandle& Handle, const FString& Text, WingOut Errors)
|
||||
{
|
||||
FProperty* Prop = Handle.GetProperty();
|
||||
|
||||
@@ -351,11 +351,11 @@ bool WingPropHandle::SetText(IPropertyHandle& Handle, const FString& Text)
|
||||
Req.BlueprintType = true;
|
||||
Req.Blueprintable = false;
|
||||
Req.AllowContainer = true;
|
||||
if (!UWingTypes::TextToType(Text, PinType, Req)) return false;
|
||||
if (!UWingTypes::TextToType(Text, PinType, Req, Errors)) return false;
|
||||
void* Data = nullptr;
|
||||
if (Handle.GetValueData(Data) != FPropertyAccess::Success || !Data)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Cannot access data for property '%s'\n"),
|
||||
Errors.Printf(TEXT("ERROR: Cannot access data for property '%s'\n"),
|
||||
*WingUtils::FormatName(Prop));
|
||||
return false;
|
||||
}
|
||||
@@ -375,12 +375,12 @@ bool WingPropHandle::SetText(IPropertyHandle& Handle, const FString& Text)
|
||||
Req.BlueprintType = true;
|
||||
Req.Blueprintable = false;
|
||||
Req.IsChildOf = ClassProp->MetaClass;
|
||||
Class = UWingTypes::TextToOneObjectType(Text, Req);
|
||||
Class = UWingTypes::TextToOneObjectType(Text, Req, Errors);
|
||||
if (!Class) return false;
|
||||
}
|
||||
if (Handle.SetValue(Class) != FPropertyAccess::Success)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to set class property '%s'\n"),
|
||||
Errors.Printf(TEXT("ERROR: Failed to set class property '%s'\n"),
|
||||
*WingUtils::FormatName(Prop));
|
||||
return false;
|
||||
}
|
||||
@@ -397,14 +397,14 @@ bool WingPropHandle::SetText(IPropertyHandle& Handle, const FString& Text)
|
||||
if (Enum != nullptr)
|
||||
{
|
||||
int64 EnumValue;
|
||||
if (!WingUtils::StringToEnum(Enum, Value, EnumValue)) return false;
|
||||
if (!WingUtils::StringToEnum(Enum, Value, EnumValue, Errors)) return false;
|
||||
Value = Enum->GetNameStringByValue(EnumValue);
|
||||
}
|
||||
|
||||
FPropertyAccess::Result Result = Handle.SetValueFromFormattedString(Value);
|
||||
if (Result != FPropertyAccess::Success)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to parse '%s' for property '%s' (type: %s)\n"),
|
||||
Errors.Printf(TEXT("ERROR: Failed to parse '%s' for property '%s' (type: %s)\n"),
|
||||
*Value, *WingUtils::FormatName(Prop), *Prop->GetCPPType());
|
||||
return false;
|
||||
}
|
||||
@@ -417,14 +417,14 @@ bool WingPropHandle::SetText(IPropertyHandle& Handle, const FString& Text)
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool WingPropHandle::SetJson(IPropertyHandle& Handle, const TSharedPtr<FJsonValue>& JsonValue)
|
||||
bool WingPropHandle::SetJson(IPropertyHandle& Handle, const TSharedPtr<FJsonValue>& JsonValue, WingOut Errors)
|
||||
{
|
||||
FPropertyAccess::Result Result;
|
||||
|
||||
switch (JsonValue->Type)
|
||||
{
|
||||
case EJson::String:
|
||||
return SetText(Handle, JsonValue->AsString());
|
||||
return SetText(Handle, JsonValue->AsString(), Errors);
|
||||
|
||||
case EJson::Boolean:
|
||||
Result = Handle.SetValue(JsonValue->AsBool());
|
||||
@@ -441,34 +441,34 @@ bool WingPropHandle::SetJson(IPropertyHandle& Handle, const TSharedPtr<FJsonValu
|
||||
|
||||
if (Result != FPropertyAccess::Success)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to set property '%s'\n"),
|
||||
Errors.Printf(TEXT("ERROR: Failed to set property '%s'\n"),
|
||||
*WingUtils::FormatName(Handle.GetProperty()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingPropHandle::PopulateFromJson(TArray<TSharedPtr<IPropertyHandle>>& Props, const FJsonObject& Json, bool AllOptional)
|
||||
bool WingPropHandle::PopulateFromJson(TArray<TSharedPtr<IPropertyHandle>>& Props, const FJsonObject& Json, bool AllOptional, WingOut Errors)
|
||||
{
|
||||
bool Ok = true;
|
||||
|
||||
// Organize the properties by name.
|
||||
TMap<FName, TSharedPtr<IPropertyHandle>> OrganizedProps;
|
||||
if (!OrganizeByName(Props, OrganizedProps)) Ok = false;
|
||||
if (!OrganizeByName(Props, OrganizedProps, Errors)) Ok = false;
|
||||
|
||||
// Parse the keys in the json, make sure they're syntactically valid and
|
||||
// that they match the names of actual properties, and that there are no dups.
|
||||
TSet<FName> Specified;
|
||||
for (const auto& KV : Json.Values)
|
||||
{
|
||||
FName Name = WingUtils::CheckInternalizeID(KV.Key);
|
||||
FName Name = WingUtils::CheckInternalizeID(KV.Key, Errors);
|
||||
if (Name.IsNone()) { Ok = false; continue; }
|
||||
if (!OrganizedProps.Contains(Name))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Unknown parameter '%s'\n"), *KV.Key);
|
||||
Errors.Printf(TEXT("ERROR: Unknown parameter '%s'\n"), *KV.Key);
|
||||
Ok = false;
|
||||
}
|
||||
if (!WingUtils::FindNoDuplicateName(Specified, Name, TEXT("parameter"))) Ok = false;
|
||||
if (!WingUtils::FindNoDuplicateName(Specified, Name, TEXT("parameter"), Errors)) Ok = false;
|
||||
}
|
||||
|
||||
// Make sure that all required properties have been specified.
|
||||
@@ -480,7 +480,7 @@ bool WingPropHandle::PopulateFromJson(TArray<TSharedPtr<IPropertyHandle>>& Props
|
||||
FName Name = H->GetProperty()->GetFName();
|
||||
if (!Specified.Contains(Name))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Required parameter %s not specified\n"),
|
||||
Errors.Printf(TEXT("Required parameter %s not specified\n"),
|
||||
*WingUtils::ExternalizeID(Name));
|
||||
Ok = false;
|
||||
}
|
||||
@@ -494,8 +494,8 @@ bool WingPropHandle::PopulateFromJson(TArray<TSharedPtr<IPropertyHandle>>& Props
|
||||
// point, we're committed.
|
||||
for (const auto& KV : Json.Values)
|
||||
{
|
||||
FName Name = WingUtils::CheckInternalizeID(KV.Key);
|
||||
if (!SetJson(*OrganizedProps[Name], KV.Value)) Ok = false;
|
||||
FName Name = WingUtils::CheckInternalizeID(KV.Key, Errors);
|
||||
if (!SetJson(*OrganizedProps[Name], KV.Value, Errors)) Ok = false;
|
||||
}
|
||||
return Ok;
|
||||
}
|
||||
|
||||
@@ -14,32 +14,313 @@
|
||||
#include "Dom/JsonValue.h"
|
||||
|
||||
|
||||
static bool IsPinTypeProperty(FProperty* Prop)
|
||||
bool FWingProperty::SetObject(UObject *Obj, WingOut Errors) const
|
||||
{
|
||||
FStructProperty* StructProp = CastField<FStructProperty>(Prop);
|
||||
return StructProp && StructProp->Struct == FEdGraphPinType::StaticStruct();
|
||||
FObjectPropertyBase *OProp = CastField<FObjectPropertyBase>(Prop);
|
||||
if (!OProp)
|
||||
{
|
||||
PrintExpectsReceived(TEXT("object"), Errors);
|
||||
return false;
|
||||
}
|
||||
if (Obj)
|
||||
{
|
||||
if (!Obj->IsA(OProp->PropertyClass))
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' expects %s, but received %s\n"),
|
||||
*WingUtils::FormatName(Prop), *OProp->PropertyClass->GetName(), *Obj->GetClass()->GetName());
|
||||
return false;
|
||||
}
|
||||
if (FClassProperty *CProp = CastField<FClassProperty>(Prop))
|
||||
{
|
||||
UClass *Class = CastChecked<UClass>(Obj);
|
||||
if (!Class->IsChildOf(CProp->MetaClass))
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' expects a subclass of %s, but received %s\n"),
|
||||
*WingUtils::FormatName(Prop), *CProp->MetaClass->GetName(), *Class->GetName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
OProp->SetObjectPropertyValue_InContainer(Container, Obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
FWingProperty::FWingProperty(FProperty* InProp, void* InContainer)
|
||||
: Prop(InProp), Container(InContainer) {}
|
||||
|
||||
FWingProperty::FWingProperty(FProperty* InProp, UObject* InContainer)
|
||||
: Prop(InProp), Container(static_cast<void*>(InContainer)) {}
|
||||
|
||||
FString FWingProperty::GetCategory()
|
||||
bool FWingProperty::SetDouble(double D, WingOut Errors) const
|
||||
{
|
||||
FString Result = Prop->GetMetaData(TEXT("Category"));
|
||||
if (Result.IsEmpty()) Result = "Unclassified";
|
||||
return Result;
|
||||
FNumericProperty *NProp = CastField<FNumericProperty>(Prop);
|
||||
if (!NProp)
|
||||
{
|
||||
PrintExpectsReceived(TEXT("double"), Errors);
|
||||
return false;
|
||||
}
|
||||
if (NProp->IsFloatingPoint())
|
||||
{
|
||||
uint8 buffer[16];
|
||||
NProp->SetFloatingPointPropertyValue(buffer, D);
|
||||
if (!FMath::IsFinite(NProp->GetFloatingPointPropertyValue(buffer)))
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' of type %s cannot hold %lf\n"),
|
||||
*WingUtils::FormatName(Prop), *Prop->GetCPPType(), D);
|
||||
return false;
|
||||
}
|
||||
Prop->SetValue_InContainer(Container, buffer);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8 buffer[16];
|
||||
if (FMath::Floor(D) != D)
|
||||
{
|
||||
PrintExpectsReceived(TEXT("double"), Errors);
|
||||
return false;
|
||||
}
|
||||
if (FMath::Abs(D) > (double)((1LL)<<53))
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: To store very large numbers in '%s', do not pass them as double. Use string or int.\n"),
|
||||
*WingUtils::FormatName(Prop));
|
||||
return false;
|
||||
}
|
||||
int64 I = (int64)D;
|
||||
NProp->SetIntPropertyValue(buffer, I);
|
||||
if (NProp->GetSignedIntPropertyValue(buffer) != I)
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' of type %s cannot hold %lld\n"),
|
||||
*WingUtils::FormatName(Prop), *Prop->GetCPPType(), I);
|
||||
return false;
|
||||
}
|
||||
NProp->SetValue_InContainer(Container, buffer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool FWingProperty::SetInt64(int64 I, WingOut Errors) const
|
||||
{
|
||||
FNumericProperty *NProp = CastField<FNumericProperty>(Prop);
|
||||
if (!NProp)
|
||||
{
|
||||
PrintExpectsReceived(TEXT("int"), Errors);
|
||||
return false;
|
||||
}
|
||||
if (NProp->IsFloatingPoint())
|
||||
{
|
||||
uint8 buffer[16];
|
||||
double D = I;
|
||||
NProp->SetFloatingPointPropertyValue(buffer, D);
|
||||
int64 RT = (int64)NProp->GetFloatingPointPropertyValue(buffer);
|
||||
if (RT != I)
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' of type %s cannot hold %lld\n"),
|
||||
*WingUtils::FormatName(Prop), *Prop->GetCPPType(), I);
|
||||
return false;
|
||||
}
|
||||
Prop->SetValue_InContainer(Container, buffer);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8 buffer[16];
|
||||
NProp->SetIntPropertyValue(buffer, I);
|
||||
if (NProp->GetSignedIntPropertyValue(buffer) != I)
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' of type %s cannot hold %lld\n"),
|
||||
*WingUtils::FormatName(Prop), *Prop->GetCPPType(), I);
|
||||
return false;
|
||||
}
|
||||
NProp->SetValue_InContainer(Container, buffer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool FWingProperty::SetBool(bool B, WingOut Errors) const
|
||||
{
|
||||
if (FBoolProperty* BoolProp = CastField<FBoolProperty>(Prop))
|
||||
{
|
||||
Prop->SetValue_InContainer(Container, &B);
|
||||
return true;
|
||||
}
|
||||
PrintExpectsReceived(TEXT("boolean"), Errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FWingProperty::SetText(FString Value, WingOut Errors) const
|
||||
{
|
||||
// Pin types get parsed by UWingTypes.
|
||||
if (IsPinTypeProperty(Prop))
|
||||
{
|
||||
FEdGraphPinType PinType;
|
||||
UWingTypes::Requirements Req;
|
||||
Req.BlueprintType = true;
|
||||
Req.Blueprintable = false;
|
||||
Req.AllowContainer = true;
|
||||
if (!UWingTypes::TextToType(Value, PinType, Req, Errors)) return false;
|
||||
Prop->SetValue_InContainer(Container, &PinType);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If it's an enum type, use our parsing routine which is smarter about
|
||||
// prefixes than ImportText. We canonicalize the string, and then send
|
||||
// it onward to ImportText.
|
||||
UEnum *Enum = nullptr;
|
||||
if (FByteProperty* ByteProp = CastField<FByteProperty>(Prop))
|
||||
Enum = ByteProp->Enum;
|
||||
if (FEnumProperty* EnumProp = CastField<FEnumProperty>(Prop))
|
||||
Enum = EnumProp->GetEnum();
|
||||
if (Enum != nullptr)
|
||||
{
|
||||
int64 EnumValue;
|
||||
if (!WingUtils::StringToEnum(Enum, Value, EnumValue, Errors)) return false;
|
||||
Value = Enum->GetNameStringByValue(EnumValue);
|
||||
}
|
||||
|
||||
// Now Use ImportText
|
||||
const TCHAR* Result = Prop->ImportText_InContainer(*Value, Container, nullptr, PPF_None);
|
||||
if ((!Result) || (*Result != 0))
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Failed to parse '%s' for property '%s' (type: %s)\n"),
|
||||
*Value, *WingUtils::FormatName(Prop), *Prop->GetCPPType());
|
||||
return false;
|
||||
}
|
||||
if (!CheckImportTextResult(Value, Errors)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FWingProperty::SetJson(const FJsonValue &JsonValue, WingOut Errors) const
|
||||
{
|
||||
if (JsonValue.Type == EJson::String)
|
||||
{
|
||||
return SetText(JsonValue.AsString(), Errors);
|
||||
}
|
||||
|
||||
if (JsonValue.Type == EJson::Number)
|
||||
{
|
||||
return SetDouble(JsonValue.AsNumber(), Errors);
|
||||
}
|
||||
|
||||
if (JsonValue.Type == EJson::Boolean)
|
||||
{
|
||||
return SetBool(JsonValue.AsBool(), Errors);
|
||||
}
|
||||
|
||||
if (JsonValue.Type == EJson::Object)
|
||||
{
|
||||
FStructProperty* StructProp = CastField<FStructProperty>(Prop);
|
||||
if (StructProp && (StructProp->Struct == FWingJsonObject::StaticStruct()))
|
||||
{
|
||||
FWingJsonObject Val;
|
||||
Val.Json = JsonValue.AsObject();
|
||||
Prop->SetValue_InContainer(Container, &Val);
|
||||
return true;
|
||||
}
|
||||
PrintExpectsReceived(TEXT("json object"), Errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (JsonValue.Type == EJson::Array)
|
||||
{
|
||||
FStructProperty* StructProp = CastField<FStructProperty>(Prop);
|
||||
if (StructProp && (StructProp->Struct == FWingJsonArray::StaticStruct()))
|
||||
{
|
||||
FWingJsonArray Val;
|
||||
Val.Array = JsonValue.AsArray();
|
||||
Prop->SetValue_InContainer(Container, &Val);
|
||||
return true;
|
||||
}
|
||||
PrintExpectsReceived(TEXT("json array"), Errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
PrintExpectsReceived(TEXT("Unrecognized Json Data"), Errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
TOptional<UObject*> FWingProperty::GetObject(WingOut Errors) const
|
||||
{
|
||||
FObjectPropertyBase *OProp = CastField<FObjectPropertyBase>(Prop);
|
||||
if (!OProp)
|
||||
{
|
||||
PrintExpectsReceived(TEXT("object"), Errors);
|
||||
return {};
|
||||
}
|
||||
uint8 *VP = Prop->ContainerPtrToValuePtr<uint8>(Container);
|
||||
return OProp->GetObjectPropertyValue(VP);
|
||||
}
|
||||
|
||||
TOptional<double> FWingProperty::GetDouble(WingOut Errors) const
|
||||
{
|
||||
FNumericProperty *NProp = CastField<FNumericProperty>(Prop);
|
||||
if (!NProp)
|
||||
{
|
||||
PrintExpectsReceived(TEXT("double"), Errors);
|
||||
return {};
|
||||
}
|
||||
uint8 *VP = Prop->ContainerPtrToValuePtr<uint8>(Container);
|
||||
if (NProp->IsFloatingPoint())
|
||||
{
|
||||
return NProp->GetFloatingPointPropertyValue(VP);
|
||||
}
|
||||
else
|
||||
{
|
||||
int64 I = NProp->GetSignedIntPropertyValue(VP);
|
||||
double D = (double)I;
|
||||
if ((int64)D != I)
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' value %lld cannot be represented losslessly as double\n"),
|
||||
*WingUtils::FormatName(Prop), I);
|
||||
return {};
|
||||
}
|
||||
return D;
|
||||
}
|
||||
}
|
||||
|
||||
TOptional<int64> FWingProperty::GetInt64(WingOut Errors) const
|
||||
{
|
||||
FNumericProperty *NProp = CastField<FNumericProperty>(Prop);
|
||||
if (!NProp)
|
||||
{
|
||||
PrintExpectsReceived(TEXT("int"), Errors);
|
||||
return {};
|
||||
}
|
||||
uint8 *VP = Prop->ContainerPtrToValuePtr<uint8>(Container);
|
||||
if (NProp->IsFloatingPoint())
|
||||
{
|
||||
double D = NProp->GetFloatingPointPropertyValue(VP);
|
||||
if (FMath::Floor(D) != D)
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' value %lf is not an integer\n"),
|
||||
*WingUtils::FormatName(Prop), D);
|
||||
return {};
|
||||
}
|
||||
if (FMath::Abs(D) > (double)((1LL)<<53))
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Property '%s' value %lf is too large to convert to int64 losslessly\n"),
|
||||
*WingUtils::FormatName(Prop), D);
|
||||
return {};
|
||||
}
|
||||
return (int64)D;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NProp->GetSignedIntPropertyValue(VP);
|
||||
}
|
||||
}
|
||||
|
||||
TOptional<bool> FWingProperty::GetBool(WingOut Errors) const
|
||||
{
|
||||
if (FBoolProperty* BoolProp = CastField<FBoolProperty>(Prop))
|
||||
{
|
||||
uint8 *VP = Prop->ContainerPtrToValuePtr<uint8>(Container);
|
||||
return BoolProp->GetPropertyValue(VP);
|
||||
}
|
||||
PrintExpectsReceived(TEXT("boolean"), Errors);
|
||||
return {};
|
||||
}
|
||||
|
||||
FString FWingProperty::GetText() const
|
||||
{
|
||||
if (IsPinTypeProperty(Prop))
|
||||
{
|
||||
FEdGraphPinType PinType;
|
||||
Prop->GetValue_InContainer(Container, &PinType);
|
||||
return UWingTypes::TypeToText(PinType);
|
||||
FEdGraphPinType *PinType = Prop->ContainerPtrToValuePtr<FEdGraphPinType>(Container);
|
||||
return UWingTypes::TypeToText(*PinType);
|
||||
}
|
||||
FString Result;
|
||||
Prop->ExportTextItem_InContainer(Result, Container, nullptr, nullptr, PPF_None);
|
||||
@@ -56,269 +337,35 @@ FString FWingProperty::GetTruncatedText(int32 MaxLen) const
|
||||
return Result;
|
||||
}
|
||||
|
||||
void FWingProperty::PrintExpectsReceived(const TCHAR *Type)
|
||||
|
||||
FString FWingProperty::GetCategory() const
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: '%s' received a %s, but expects %s\n"),
|
||||
*WingUtils::FormatName(Prop), Type, *Prop->GetCPPType());
|
||||
FString Result = Prop->GetMetaData(TEXT("Category"));
|
||||
if (Result.IsEmpty()) Result = "Unclassified";
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
bool FWingProperty::CheckImportTextResult(const FString &Value)
|
||||
void FWingProperty::GetAll(FWingStructAndUStruct Obj, EPropertyFlags Flags, TArray<FWingProperty> &Props)
|
||||
{
|
||||
uint8 *VP = Prop->ContainerPtrToValuePtr<uint8>(Container);
|
||||
if (FObjectPropertyBase *OProp = CastField<FObjectPropertyBase>(Prop))
|
||||
{
|
||||
UObject *Obj = OProp->GetObjectPropertyValue(VP);
|
||||
if (Obj == nullptr && Value.TrimStartAndEnd().Compare(TEXT("None"), ESearchCase::IgnoreCase) != 0)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to parse '%s' for property '%s'\n"),
|
||||
*Value, *WingUtils::FormatName(Prop));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FWingProperty::SetText(FString Value)
|
||||
{
|
||||
// Pin types get parsed by UWingTypes.
|
||||
if (IsPinTypeProperty(Prop))
|
||||
{
|
||||
FEdGraphPinType PinType;
|
||||
UWingTypes::Requirements Req;
|
||||
Req.BlueprintType = true;
|
||||
Req.Blueprintable = false;
|
||||
Req.AllowContainer = true;
|
||||
if (!UWingTypes::TextToType(Value, PinType, Req)) return false;
|
||||
Prop->SetValue_InContainer(Container, &PinType);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If it's an enum type, use our parsing routine which is smarter about
|
||||
// prefixes than ImportText. We canonicalize the string, and then send
|
||||
// it onward to ImportText.
|
||||
UEnum *Enum = nullptr;
|
||||
if (FByteProperty* ByteProp = CastField<FByteProperty>(Prop))
|
||||
Enum = ByteProp->Enum;
|
||||
if (FEnumProperty* EnumProp = CastField<FEnumProperty>(Prop))
|
||||
Enum = EnumProp->GetEnum();
|
||||
if (Enum != nullptr)
|
||||
{
|
||||
int64 EnumValue;
|
||||
if (!WingUtils::StringToEnum(Enum, Value, EnumValue)) return false;
|
||||
Value = Enum->GetNameStringByValue(EnumValue);
|
||||
}
|
||||
|
||||
// Now Use ImportText
|
||||
const TCHAR* Result = Prop->ImportText_InContainer(*Value, Container, nullptr, PPF_None);
|
||||
if ((!Result) || (*Result != 0))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to parse '%s' for property '%s' (type: %s)\n"),
|
||||
*Value, *WingUtils::FormatName(Prop), *Prop->GetCPPType());
|
||||
return false;
|
||||
}
|
||||
if (!CheckImportTextResult(Value)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FWingProperty::SetDouble(double D)
|
||||
{
|
||||
FNumericProperty *NProp = CastField<FNumericProperty>(Prop);
|
||||
if (!NProp)
|
||||
{
|
||||
PrintExpectsReceived(TEXT("double"));
|
||||
return false;
|
||||
}
|
||||
if (NProp->IsFloatingPoint())
|
||||
{
|
||||
uint8 buffer[16];
|
||||
NProp->SetFloatingPointPropertyValue(buffer, D);
|
||||
if (!FMath::IsFinite(NProp->GetFloatingPointPropertyValue(buffer)))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Property '%s' of type %s cannot hold %lf\n"),
|
||||
*WingUtils::FormatName(Prop), *Prop->GetCPPType(), D);
|
||||
return false;
|
||||
}
|
||||
Prop->SetValue_InContainer(Container, buffer);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8 buffer[16];
|
||||
if (FMath::Floor(D) != D)
|
||||
{
|
||||
PrintExpectsReceived(TEXT("double"));
|
||||
return false;
|
||||
}
|
||||
if (FMath::Abs(D) > (double)((1LL)<<53))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: To store very large numbers in '%s', do not pass them as double. Use string or int.\n"),
|
||||
*WingUtils::FormatName(Prop));
|
||||
return false;
|
||||
}
|
||||
int64 I = (int64)D;
|
||||
NProp->SetIntPropertyValue(buffer, I);
|
||||
if (NProp->GetSignedIntPropertyValue(buffer) != I)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Property '%s' of type %s cannot hold %lld\n"),
|
||||
*WingUtils::FormatName(Prop), *Prop->GetCPPType(), I);
|
||||
return false;
|
||||
}
|
||||
NProp->SetValue_InContainer(Container, buffer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool FWingProperty::SetInt64(int64 I)
|
||||
{
|
||||
FNumericProperty *NProp = CastField<FNumericProperty>(Prop);
|
||||
if (!NProp)
|
||||
{
|
||||
PrintExpectsReceived(TEXT("int"));
|
||||
return false;
|
||||
}
|
||||
if (NProp->IsFloatingPoint())
|
||||
{
|
||||
uint8 buffer[16];
|
||||
double D = I;
|
||||
NProp->SetFloatingPointPropertyValue(buffer, D);
|
||||
int64 RT = (int64)NProp->GetFloatingPointPropertyValue(buffer);
|
||||
if (RT != I)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Property '%s' of type %s cannot hold %lld\n"),
|
||||
*WingUtils::FormatName(Prop), *Prop->GetCPPType(), I);
|
||||
return false;
|
||||
}
|
||||
Prop->SetValue_InContainer(Container, buffer);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8 buffer[16];
|
||||
NProp->SetIntPropertyValue(buffer, I);
|
||||
if (NProp->GetSignedIntPropertyValue(buffer) != I)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Property '%s' of type %s cannot hold %lld\n"),
|
||||
*WingUtils::FormatName(Prop), *Prop->GetCPPType(), I);
|
||||
return false;
|
||||
}
|
||||
NProp->SetValue_InContainer(Container, buffer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool FWingProperty::SetBool(bool B)
|
||||
{
|
||||
if (FBoolProperty* BoolProp = CastField<FBoolProperty>(Prop))
|
||||
{
|
||||
Prop->SetValue_InContainer(Container, &B);
|
||||
return true;
|
||||
}
|
||||
PrintExpectsReceived(TEXT("boolean"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool FWingProperty::SetJson(const TSharedPtr<FJsonValue> &JsonValue)
|
||||
{
|
||||
if (JsonValue->Type == EJson::String)
|
||||
{
|
||||
return SetText(JsonValue->AsString());
|
||||
}
|
||||
|
||||
if (JsonValue->Type == EJson::Number)
|
||||
{
|
||||
return SetDouble(JsonValue->AsNumber());
|
||||
}
|
||||
|
||||
if (JsonValue->Type == EJson::Boolean)
|
||||
{
|
||||
return SetBool(JsonValue->AsBool());
|
||||
}
|
||||
|
||||
if (JsonValue->Type == EJson::Object)
|
||||
{
|
||||
void* ValuePtr = Prop->ContainerPtrToValuePtr<void>(Container);
|
||||
FStructProperty* StructProp = CastField<FStructProperty>(Prop);
|
||||
if (StructProp && (StructProp->Struct == FWingJsonObject::StaticStruct()))
|
||||
{
|
||||
static_cast<FWingJsonObject*>(ValuePtr)->Json = JsonValue->AsObject();
|
||||
return true;
|
||||
}
|
||||
PrintExpectsReceived(TEXT("json object"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (JsonValue->Type == EJson::Array)
|
||||
{
|
||||
void* ValuePtr = Prop->ContainerPtrToValuePtr<void>(Container);
|
||||
FStructProperty* StructProp = CastField<FStructProperty>(Prop);
|
||||
if (StructProp && (StructProp->Struct == FWingJsonArray::StaticStruct()))
|
||||
{
|
||||
static_cast<FWingJsonArray*>(ValuePtr)->Array = JsonValue->AsArray();
|
||||
return true;
|
||||
}
|
||||
PrintExpectsReceived(TEXT("json array"));
|
||||
return false;
|
||||
}
|
||||
|
||||
PrintExpectsReceived(TEXT("Unrecognized Json Data"));
|
||||
return false;
|
||||
}
|
||||
|
||||
void FWingProperty::Collect(UStruct* StructType, void* Container, TArray<FWingProperty> &Props, EPropertyFlags Flags)
|
||||
{
|
||||
TMap<FString, TArray<FWingProperty>> Grouped;
|
||||
|
||||
for (TFieldIterator<FProperty> It(StructType); It; ++It)
|
||||
TArray<FWingProperty> Result;
|
||||
for (TFieldIterator<FProperty> It(Obj.UStructPtr); It; ++It)
|
||||
{
|
||||
if (Flags != 0 && !It->HasAnyPropertyFlags(Flags)) continue;
|
||||
FString SortCat = *It->GetMetaData(TEXT("Category"));
|
||||
Grouped.FindOrAdd(SortCat).Add(FWingProperty(*It, Container));
|
||||
}
|
||||
TArray<FString> Categories;
|
||||
|
||||
Grouped.GetKeys(Categories);
|
||||
Categories.Sort([](const FString& A, const FString& B) {
|
||||
if (A.IsEmpty()) return false;
|
||||
if (B.IsEmpty()) return true;
|
||||
return A < B;
|
||||
});
|
||||
|
||||
for (const FString& Category : Categories)
|
||||
{
|
||||
Props.Append(Grouped[Category]);
|
||||
Result.Add(FWingProperty(*It, Obj.StructPtr));
|
||||
}
|
||||
}
|
||||
|
||||
TArray<FWingProperty> FWingProperty::GetAll(UObject* Object, EPropertyFlags Flags)
|
||||
{
|
||||
return GetAll(Object->GetClass(), Object, Flags);
|
||||
}
|
||||
|
||||
TArray<FWingProperty> FWingProperty::GetAll(UStruct* StructType, void* Container, EPropertyFlags Flags)
|
||||
TArray<FWingProperty> FWingProperty::GetAll(FWingStructAndUStruct Obj, EPropertyFlags Flags)
|
||||
{
|
||||
TArray<FWingProperty> Result;
|
||||
Collect(StructType, Container, Result, Flags);
|
||||
GetAll(Obj, Flags, Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
TArray<FWingProperty> FWingProperty::GetNamed(UStruct* StructType, void* Container, const TArray<FName> &Names)
|
||||
{
|
||||
TArray<FWingProperty> Result;
|
||||
for (FName Name : Names)
|
||||
{
|
||||
FProperty *Prop = StructType->FindPropertyByName(Name);
|
||||
if (Prop != nullptr) Result.Emplace(Prop, Container);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
TArray<FName> FWingProperty::GetNames(UStruct *StructType, EPropertyFlags Flags)
|
||||
TArray<FName> FWingProperty::GetNames(UStruct *US, EPropertyFlags Flags)
|
||||
{
|
||||
TArray<FName> Result;
|
||||
for (TFieldIterator<FProperty> It(StructType); It; ++It)
|
||||
for (TFieldIterator<FProperty> It(US); It; ++It)
|
||||
{
|
||||
if (Flags != 0 && !It->HasAnyPropertyFlags(Flags)) continue;
|
||||
Result.Add(It->GetFName());
|
||||
@@ -326,29 +373,23 @@ TArray<FName> FWingProperty::GetNames(UStruct *StructType, EPropertyFlags Flags)
|
||||
return Result;
|
||||
}
|
||||
|
||||
void FWingProperty::Remove(TArray<FWingProperty>& Props, const FString& Name)
|
||||
void FWingProperty::Remove(TArray<FWingProperty>& Props, FName Name)
|
||||
{
|
||||
Props.RemoveAll([&](const FWingProperty& P) { return P.Prop->GetName() == Name; });
|
||||
}
|
||||
|
||||
void FWingProperty::Move(TArray<FWingProperty> &Out, TArray<FWingProperty> &In, const FString &Name)
|
||||
void FWingProperty::Move(TArray<FWingProperty> &Out, TArray<FWingProperty> &In, FName Name)
|
||||
{
|
||||
int Dst = 0;
|
||||
for (int i = 0; i < In.Num(); i++)
|
||||
{
|
||||
if (In[i]->GetName() == Name)
|
||||
{
|
||||
Out.Add(In[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
In[Dst++] = In[i];
|
||||
}
|
||||
if (In[i]->GetFName() == Name) Out.Add(In[i]);
|
||||
else In[Dst++] = In[i];
|
||||
}
|
||||
In.SetNum(Dst);
|
||||
}
|
||||
|
||||
TArray<FWingProperty> FWingProperty::GetDetailsGeneral(UObject* Obj, EPropertyFlags Flags, bool Mutable)
|
||||
TArray<FWingProperty> FWingProperty::GetDetails(UObject* Obj, EPropertyFlags Flags, bool Mutable)
|
||||
{
|
||||
if (!Obj) return {};
|
||||
|
||||
@@ -358,7 +399,7 @@ TArray<FWingProperty> FWingProperty::GetDetailsGeneral(UObject* Obj, EPropertyFl
|
||||
{
|
||||
if (BP->GeneratedClass == nullptr)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Blueprint '%s' has no GeneratedClass\n"), *Obj->GetName());
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Blueprint '%s' has no GeneratedClass\n"), *Obj->GetName());
|
||||
return {};
|
||||
}
|
||||
Obj = BP->GeneratedClass->GetDefaultObject();
|
||||
@@ -370,13 +411,12 @@ TArray<FWingProperty> FWingProperty::GetDetailsGeneral(UObject* Obj, EPropertyFl
|
||||
Obj = Mutable ? Ref->GetMutableTemplate() : Ref->GetImmutableTemplate();
|
||||
if (!Obj)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Component '%s' has no template\n"), *Ref->VariableName.ToString());
|
||||
WingOut::Stdout.Printf(TEXT("ERROR: Component '%s' has no template\n"), *Ref->VariableName.ToString());
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
TArray<FWingProperty> Result;
|
||||
Collect(Obj->GetClass(), Obj, Result, Flags);
|
||||
TArray<FWingProperty> Result = GetAll(Obj, Flags);
|
||||
|
||||
// If it's a Material Graph node, also collect properties from
|
||||
// the associated material expression.
|
||||
@@ -385,7 +425,7 @@ TArray<FWingProperty> FWingProperty::GetDetailsGeneral(UObject* Obj, EPropertyFl
|
||||
{
|
||||
if (UMaterialExpression* Expr = MatNode->MaterialExpression)
|
||||
{
|
||||
Collect(Expr->GetClass(), Expr, Result, Flags);
|
||||
GetAll(Expr, Flags, Result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,7 +436,7 @@ TArray<FWingProperty> FWingProperty::GetDetailsGeneral(UObject* Obj, EPropertyFl
|
||||
FWingProperty::Remove(Result, TEXT("Slot"));
|
||||
if (UPanelSlot* Slot = Widget->Slot)
|
||||
{
|
||||
Collect(Slot->GetClass(), Slot, Result, Flags);
|
||||
GetAll(Slot, Flags, Result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,50 +444,29 @@ TArray<FWingProperty> FWingProperty::GetDetailsGeneral(UObject* Obj, EPropertyFl
|
||||
}
|
||||
|
||||
|
||||
TArray<FWingProperty> FWingProperty::FindAllSubstring(const TArray<FWingProperty>& Props, const FString& Substring)
|
||||
{
|
||||
if (Substring.IsEmpty()) return Props;
|
||||
TArray<FWingProperty> Result;
|
||||
for (const FWingProperty& P : Props)
|
||||
{
|
||||
if (WingUtils::FormatName(P.Prop).Contains(Substring, ESearchCase::IgnoreCase))
|
||||
Result.Add(P);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool FWingProperty::PopulateFromJson(FWingProperty& P, const FJsonObject* Json, bool AllOptional)
|
||||
{
|
||||
FString JsonKey = WingUtils::FormatName(P.Prop);
|
||||
TSharedPtr<FJsonValue> Value = Json->TryGetField(JsonKey);
|
||||
|
||||
if (Value == nullptr)
|
||||
{
|
||||
bool Optional = AllOptional || P.Prop->HasMetaData(TEXT("Optional"));
|
||||
if (Optional) return true;
|
||||
UWingServer::Printf(TEXT("ERROR: Missing required parameter '%s'\n"), *JsonKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
return P.SetJson(Value);
|
||||
}
|
||||
|
||||
bool FWingProperty::PopulateFromJson(
|
||||
TArray<FWingProperty>& Props, const FJsonObject* Json, bool AllOptional)
|
||||
bool FWingProperty::PopulateFromJson(TArray<FWingProperty>& Props, const FJsonValue& Json, bool AllOptional, WingOut Errors)
|
||||
{
|
||||
bool Ok = true;
|
||||
|
||||
// Build a set of known property names for the unknown-field check.
|
||||
TSet<FString> KnownKeys;
|
||||
for (const FWingProperty& P : Props)
|
||||
KnownKeys.Add(WingUtils::FormatName(P.Prop));
|
||||
|
||||
// Check for unknown fields in the JSON
|
||||
for (const auto& KV : Json->Values)
|
||||
// Make sure they passed in a JSON object.
|
||||
TSharedPtr<FJsonObject> Obj = Json.AsObject();
|
||||
if (Obj == nullptr)
|
||||
{
|
||||
if (!KnownKeys.Contains(KV.Key))
|
||||
Errors.Printf(TEXT("property data should be stored in a json object\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Build a set of known property names for the unknown-field check.
|
||||
TSet<FName> KnownKeys;
|
||||
for (const FWingProperty& P : Props) KnownKeys.Add(P->GetFName());
|
||||
|
||||
// Check for unknown fields in the JSON
|
||||
for (const auto& KV : Obj->Values)
|
||||
{
|
||||
FName Name = WingUtils::CheckInternalizeID(KV.Key, Errors);
|
||||
if (!KnownKeys.Contains(Name))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Unknown parameter '%s'\n"), *KV.Key);
|
||||
Errors.Printf(TEXT("ERROR: Unknown parameter '%s'\n"), *KV.Key);
|
||||
Ok = false;
|
||||
}
|
||||
}
|
||||
@@ -455,23 +474,51 @@ bool FWingProperty::PopulateFromJson(
|
||||
// Populate each property from JSON
|
||||
for (FWingProperty& P : Props)
|
||||
{
|
||||
if (!PopulateFromJson(P, Json, AllOptional)) Ok = false;
|
||||
FString JsonKey = WingUtils::FormatName(P.Prop);
|
||||
TSharedPtr<FJsonValue> Value = Obj->TryGetField(JsonKey);
|
||||
if (!Value)
|
||||
{
|
||||
bool Optional = AllOptional || P.Prop->HasMetaData(TEXT("Optional"));
|
||||
if (!Optional)
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Missing required parameter '%s'\n"), *JsonKey);
|
||||
Ok = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!P.SetJson(*Value, Errors)) Ok = false;
|
||||
}
|
||||
return Ok;
|
||||
}
|
||||
|
||||
bool FWingProperty::PopulateFromJson(UStruct* StructType, void* Container, const FJsonObject* Object)
|
||||
|
||||
bool FWingProperty::IsPinTypeProperty(FProperty* Prop)
|
||||
{
|
||||
TArray<FWingProperty> Props = FWingProperty::GetAll(StructType, Container, (EPropertyFlags)0);
|
||||
return PopulateFromJson(Props, Object);
|
||||
FStructProperty* StructProp = CastField<FStructProperty>(Prop);
|
||||
return StructProp && StructProp->Struct == FEdGraphPinType::StaticStruct();
|
||||
}
|
||||
|
||||
bool FWingProperty::PopulateFromJson(UStruct* StructType, void* Container, const TSharedPtr<FJsonValue>& Object)
|
||||
|
||||
|
||||
void FWingProperty::PrintExpectsReceived(const TCHAR *Type, WingOut Errors) const
|
||||
{
|
||||
if (!Object.IsValid() || (Object->Type != EJson::Object))
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Expected a JSON object\n"));
|
||||
return false;
|
||||
}
|
||||
return PopulateFromJson(StructType, Container, Object->AsObject().Get());
|
||||
Errors.Printf(TEXT("ERROR: '%s' received a %s, but expects %s\n"),
|
||||
*WingUtils::FormatName(Prop), Type, *Prop->GetCPPType());
|
||||
}
|
||||
|
||||
|
||||
bool FWingProperty::CheckImportTextResult(const FString &Value, WingOut Errors) const
|
||||
{
|
||||
if (FObjectPropertyBase *OProp = CastField<FObjectPropertyBase>(Prop))
|
||||
{
|
||||
uint8 *VP = Prop->ContainerPtrToValuePtr<uint8>(Container);
|
||||
UObject *Obj = OProp->GetObjectPropertyValue(VP);
|
||||
if (Obj == nullptr && Value.TrimStartAndEnd().Compare(TEXT("None"), ESearchCase::IgnoreCase) != 0)
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: Failed to parse '%s' for property '%s'\n"),
|
||||
*Value, *WingUtils::FormatName(Prop));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -263,7 +263,7 @@ FString UWingServer::HandleRequest(const FString& Line)
|
||||
{
|
||||
LogCapture.CapturedErrors.Empty();
|
||||
LogCapture.bEnabled = true;
|
||||
HandlerOutput.Reset();
|
||||
WingOut::StdoutBuffer.Reset();
|
||||
SuggestedManualSections.Empty();
|
||||
LastHandler = nullptr;
|
||||
|
||||
@@ -273,7 +273,7 @@ FString UWingServer::HandleRequest(const FString& Line)
|
||||
LogCapture.bEnabled = false;
|
||||
for (const FString& Msg : LogCapture.CapturedErrors)
|
||||
{
|
||||
UWingServer::Printf(TEXT("UE_LOG: %s\n"), *Msg);
|
||||
WingOut::Stdout.Printf(TEXT("UE_LOG: %s\n"), *Msg);
|
||||
}
|
||||
LogCapture.CapturedErrors.Empty();
|
||||
if (!SuggestedManualSections.IsEmpty())
|
||||
@@ -281,8 +281,8 @@ FString UWingServer::HandleRequest(const FString& Line)
|
||||
UWingServer::SuggestManual(WingManual::Section::HandlerHelp);
|
||||
WingManual::PrintManual(SuggestedManualSections, LastHandler, true);
|
||||
}
|
||||
FString Result = HandlerOutput.ToString();
|
||||
HandlerOutput.Reset();
|
||||
FString Result = WingOut::StdoutBuffer.ToString();
|
||||
WingOut::StdoutBuffer.Reset();
|
||||
for (int32 i = 0; i < Result.Len(); ++i)
|
||||
{
|
||||
if (Result[i] == TEXT('\0')) Result[i] = TEXT(' ');
|
||||
@@ -298,7 +298,7 @@ void UWingServer::TryCallHandler(const FString &Line)
|
||||
FJsonSerializer::Deserialize(Reader, Request);
|
||||
if (!Request.IsValid())
|
||||
{
|
||||
UWingServer::Printf(TEXT("Request is not valid JSON"));
|
||||
WingOut::Stdout.Printf(TEXT("Request is not valid JSON"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -306,8 +306,8 @@ void UWingServer::TryCallHandler(const FString &Line)
|
||||
FString Command;
|
||||
if (!Request->TryGetStringField(TEXT("command"), Command))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Request does not contain 'command' parameter"));
|
||||
UWingServer::Printf(TEXT("We recommend sending command='UserManual'."));
|
||||
WingOut::Stdout.Printf(TEXT("Request does not contain 'command' parameter"));
|
||||
WingOut::Stdout.Printf(TEXT("We recommend sending command='UserManual'."));
|
||||
return;
|
||||
}
|
||||
Request->RemoveField(TEXT("command"));
|
||||
@@ -316,7 +316,7 @@ void UWingServer::TryCallHandler(const FString &Line)
|
||||
FWingHandlerConfig* Found = FindHandler(Command);
|
||||
if (!Found)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Unknown command: %s"), *Command);
|
||||
WingOut::Stdout.Printf(TEXT("Unknown command: %s"), *Command);
|
||||
UWingServer::SuggestManual(WingManual::Section::ImportantCommands);
|
||||
return;
|
||||
}
|
||||
@@ -330,7 +330,7 @@ void UWingServer::TryCallHandler(const FString &Line)
|
||||
// Populate the handler object with the request parameters.
|
||||
WingPropHandle Props;
|
||||
WingPropHandle::Handles Handles = Props.AllProperties(HandlerObj.Get(), true);
|
||||
if (!WingPropHandle::PopulateFromJson(Handles, *Request, false))
|
||||
if (!WingPropHandle::PopulateFromJson(Handles, *Request, false, WingOut::Stdout))
|
||||
{
|
||||
UWingServer::SuggestManual(WingManual::Section::HandlerHelp);
|
||||
return;
|
||||
@@ -490,3 +490,7 @@ FWingHandlerConfig* UWingServer::FindHandler(const FString& Name)
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TStringBuilder<65536> WingOut::StdoutBuffer;
|
||||
WingOut WingOut::Stdout(&WingOut::StdoutBuffer);
|
||||
WingOut WingOut::None(nullptr);
|
||||
|
||||
@@ -433,124 +433,124 @@ static const FName NAME_TypeSoftClass(TEXT("SoftClass"));
|
||||
|
||||
static const FName NAME_StartOfType("Start-of-Type");
|
||||
|
||||
void UWingTypes::PrintParseError(WingTokenizer& Tok, const TCHAR* Message)
|
||||
void UWingTypes::PrintParseError(WingTokenizer& Tok, const TCHAR* Message, WingOut Errors)
|
||||
{
|
||||
FString TypeText(Tok.GetRange(NAME_StartOfType, 1));
|
||||
UWingServer::Printf(TEXT("ERROR parsing type '%s' — %s\n"), *TypeText, Message);
|
||||
Errors.Printf(TEXT("ERROR parsing type '%s' — %s\n"), *TypeText, Message);
|
||||
UWingServer::SuggestManual(WingManual::Section::Types);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool UWingTypes::ParseChar(WingTokenizer& Tok, TCHAR c)
|
||||
bool UWingTypes::ParseChar(WingTokenizer& Tok, TCHAR c, WingOut Errors)
|
||||
{
|
||||
if (!Tok.TokenIs(c))
|
||||
{
|
||||
PrintParseError(Tok, *FString::Printf(TEXT("expected '%c'"), c));
|
||||
PrintParseError(Tok, *FString::Printf(TEXT("expected '%c'"), c), Errors);
|
||||
return false;
|
||||
}
|
||||
Tok.Advance();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UWingTypes::ParsePlainIdentifier(WingTokenizer& Tok, FEdGraphPinType& OutType)
|
||||
bool UWingTypes::ParsePlainIdentifier(WingTokenizer& Tok, FEdGraphPinType& OutType, WingOut Errors)
|
||||
{
|
||||
if (!Tok.TokenIs(Tok.Identifier))
|
||||
{
|
||||
PrintParseError(Tok, TEXT("expected identifier"));
|
||||
PrintParseError(Tok, TEXT("expected identifier"), Errors);
|
||||
return false;
|
||||
}
|
||||
FString Name = Tok.NextName().ToString();
|
||||
Tok.Advance();
|
||||
return ResolveShortName(Tok, Name, OutType);
|
||||
return ResolveShortName(Tok, Name, OutType, Errors);
|
||||
}
|
||||
|
||||
bool UWingTypes::ParseWrapped(WingTokenizer& Tok, FName Wrapper, FEdGraphPinType& OutType)
|
||||
bool UWingTypes::ParseWrapped(WingTokenizer& Tok, FName Wrapper, FEdGraphPinType& OutType, WingOut Errors)
|
||||
{
|
||||
Tok.Advance();
|
||||
if (!ParseChar(Tok, '<')) return false;
|
||||
if (!ParsePlainIdentifier(Tok, OutType)) return false;
|
||||
if (!ParseChar(Tok, '<', Errors)) return false;
|
||||
if (!ParsePlainIdentifier(Tok, OutType, Errors)) return false;
|
||||
if (OutType.PinCategory != UEdGraphSchema_K2::PC_Object)
|
||||
{
|
||||
PrintParseError(Tok, *FString::Printf(TEXT("'%s' is not an object type"), *OutType.PinSubCategoryObject->GetName()));
|
||||
PrintParseError(Tok, *FString::Printf(TEXT("'%s' is not an object type"), *OutType.PinSubCategoryObject->GetName()), Errors);
|
||||
return false;
|
||||
}
|
||||
if (!ParseChar(Tok, '>')) return false;
|
||||
if (!ParseChar(Tok, '>', Errors)) return false;
|
||||
OutType.PinCategory = Wrapper;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UWingTypes::ParseMaybeWrapped(WingTokenizer& Tok, FEdGraphPinType& OutType)
|
||||
bool UWingTypes::ParseMaybeWrapped(WingTokenizer& Tok, FEdGraphPinType& OutType, WingOut Errors)
|
||||
{
|
||||
if (Tok.TokenIs(NAME_TypeSoft, '<'))
|
||||
{
|
||||
return ParseWrapped(Tok, UEdGraphSchema_K2::PC_SoftObject, OutType);
|
||||
return ParseWrapped(Tok, UEdGraphSchema_K2::PC_SoftObject, OutType, Errors);
|
||||
}
|
||||
else if (Tok.TokenIs(NAME_TypeClass, '<'))
|
||||
{
|
||||
return ParseWrapped(Tok, UEdGraphSchema_K2::PC_Class, OutType);
|
||||
return ParseWrapped(Tok, UEdGraphSchema_K2::PC_Class, OutType, Errors);
|
||||
}
|
||||
else if (Tok.TokenIs(NAME_TypeSoftClass, '<'))
|
||||
{
|
||||
return ParseWrapped(Tok, UEdGraphSchema_K2::PC_SoftClass, OutType);
|
||||
return ParseWrapped(Tok, UEdGraphSchema_K2::PC_SoftClass, OutType, Errors);
|
||||
}
|
||||
else return ParsePlainIdentifier(Tok, OutType);
|
||||
else return ParsePlainIdentifier(Tok, OutType, Errors);
|
||||
}
|
||||
|
||||
bool UWingTypes::ParseArrayOrSet(WingTokenizer& Tok, FEdGraphPinType& OutType)
|
||||
bool UWingTypes::ParseArrayOrSet(WingTokenizer& Tok, FEdGraphPinType& OutType, WingOut Errors)
|
||||
{
|
||||
Tok.Advance();
|
||||
if (!ParseChar(Tok, '<')) return false;
|
||||
if (!ParseMaybeWrapped(Tok, OutType)) return false;
|
||||
if (!ParseChar(Tok, '>')) return false;
|
||||
if (!ParseChar(Tok, '<', Errors)) return false;
|
||||
if (!ParseMaybeWrapped(Tok, OutType, Errors)) return false;
|
||||
if (!ParseChar(Tok, '>', Errors)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UWingTypes::ParseMap(WingTokenizer& Tok, FEdGraphPinType& OutType)
|
||||
bool UWingTypes::ParseMap(WingTokenizer& Tok, FEdGraphPinType& OutType, WingOut Errors)
|
||||
{
|
||||
Tok.Advance();
|
||||
if (!ParseChar(Tok, '<')) return false;
|
||||
if (!ParsePlainIdentifier(Tok, OutType)) return false;
|
||||
if (!ParseChar(Tok, ',')) return false;
|
||||
if (!ParseChar(Tok, '<', Errors)) return false;
|
||||
if (!ParsePlainIdentifier(Tok, OutType, Errors)) return false;
|
||||
if (!ParseChar(Tok, ',', Errors)) return false;
|
||||
FEdGraphPinType ValueType;
|
||||
if (!ParseMaybeWrapped(Tok, ValueType)) return false;
|
||||
if (!ParseMaybeWrapped(Tok, ValueType, Errors)) return false;
|
||||
OutType.PinValueType.TerminalCategory = ValueType.PinCategory;
|
||||
OutType.PinValueType.TerminalSubCategory = ValueType.PinSubCategory;
|
||||
OutType.PinValueType.TerminalSubCategoryObject = ValueType.PinSubCategoryObject;
|
||||
if (!ParseChar(Tok, '>')) return false;
|
||||
if (!ParseChar(Tok, '>', Errors)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UWingTypes::ParseType(WingTokenizer& Tok, FEdGraphPinType& OutType)
|
||||
bool UWingTypes::ParseType(WingTokenizer& Tok, FEdGraphPinType& OutType, WingOut Errors)
|
||||
{
|
||||
if (Tok.TokenIs(NAME_TypeArray, '<'))
|
||||
{
|
||||
OutType.ContainerType = EPinContainerType::Array;
|
||||
if (!ParseArrayOrSet(Tok, OutType)) return false;
|
||||
if (!ParseArrayOrSet(Tok, OutType, Errors)) return false;
|
||||
}
|
||||
else if (Tok.TokenIs(NAME_TypeSet, '<'))
|
||||
{
|
||||
OutType.ContainerType = EPinContainerType::Set;
|
||||
if (!ParseArrayOrSet(Tok, OutType)) return false;
|
||||
if (!ParseArrayOrSet(Tok, OutType, Errors)) return false;
|
||||
}
|
||||
else if (Tok.TokenIs(NAME_TypeMap, '<'))
|
||||
{
|
||||
OutType.ContainerType = EPinContainerType::Map;
|
||||
if (!ParseMap(Tok, OutType)) return false;
|
||||
if (!ParseMap(Tok, OutType, Errors)) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ParseMaybeWrapped(Tok, OutType)) return false;
|
||||
if (!ParseMaybeWrapped(Tok, OutType, Errors)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UWingTypes::ResolveShortName(WingTokenizer& Tok, const FString &Name, FEdGraphPinType &OutType)
|
||||
bool UWingTypes::ResolveShortName(WingTokenizer& Tok, const FString &Name, FEdGraphPinType &OutType, WingOut Errors)
|
||||
{
|
||||
Info* TypeInfo = ShortToInfo.Find(Name.ToLower());
|
||||
if (!TypeInfo)
|
||||
{
|
||||
PrintParseError(Tok, *FString::Printf(TEXT("unrecognized type '%s'"), *Name));
|
||||
PrintParseError(Tok, *FString::Printf(TEXT("unrecognized type '%s'"), *Name), Errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -566,7 +566,7 @@ bool UWingTypes::ResolveShortName(WingTokenizer& Tok, const FString &Name, FEdGr
|
||||
UObject* Obj = LoadObject<UObject>(nullptr, *TypeInfo->PinSubCategoryObject);
|
||||
if (!Obj)
|
||||
{
|
||||
PrintParseError(Tok, *FString::Printf(TEXT("failed to load type '%s' at path '%s'"), *Name, *TypeInfo->PinSubCategoryObject));
|
||||
PrintParseError(Tok, *FString::Printf(TEXT("failed to load type '%s' at path '%s'"), *Name, *TypeInfo->PinSubCategoryObject), Errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -605,7 +605,7 @@ bool UWingTypes::ResolveShortName(WingTokenizer& Tok, const FString &Name, FEdGr
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
bool UWingTypes::TextToType(WingTokenizer &Tok, FEdGraphPinType& OutPinType, const Requirements &Require, bool CheckEOF)
|
||||
bool UWingTypes::TextToType(WingTokenizer &Tok, FEdGraphPinType& OutPinType, const Requirements &Require, bool CheckEOF, WingOut Errors)
|
||||
{
|
||||
UWingTypes* Types = GEditor->GetEditorSubsystem<UWingTypes>();
|
||||
check(Types);
|
||||
@@ -615,19 +615,19 @@ bool UWingTypes::TextToType(WingTokenizer &Tok, FEdGraphPinType& OutPinType, con
|
||||
!Require.Blueprintable.IsSet() ||
|
||||
!Require.AllowContainer.IsSet())
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: TextToType called with underspecified Requirements list.\n"));
|
||||
Errors.Printf(TEXT("ERROR: TextToType called with underspecified Requirements list.\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
OutPinType = FEdGraphPinType();
|
||||
if (!Types->ParseType(Tok, OutPinType))
|
||||
if (!Types->ParseType(Tok, OutPinType, Errors))
|
||||
{
|
||||
OutPinType = FEdGraphPinType(); return false;
|
||||
}
|
||||
|
||||
if (CheckEOF && (Tok.NextType() != 0))
|
||||
{
|
||||
PrintParseError(Tok, TEXT("Extra tokens at end of Type name"));
|
||||
PrintParseError(Tok, TEXT("Extra tokens at end of Type name"), Errors);
|
||||
OutPinType = FEdGraphPinType(); return false;
|
||||
}
|
||||
|
||||
@@ -636,7 +636,7 @@ bool UWingTypes::TextToType(WingTokenizer &Tok, FEdGraphPinType& OutPinType, con
|
||||
if (OutPinType.IsContainer())
|
||||
{
|
||||
FString Text(Tok.GetRange(NAME_StartOfType, 0));
|
||||
UWingServer::Printf(TEXT("ERROR: Type '%s' is a container, not allowed here\n"), *Text);
|
||||
Errors.Printf(TEXT("ERROR: Type '%s' is a container, not allowed here\n"), *Text);
|
||||
UWingServer::SuggestManual(WingManual::Section::HandlerHelp);
|
||||
OutPinType = FEdGraphPinType(); return false;
|
||||
}
|
||||
@@ -646,7 +646,7 @@ bool UWingTypes::TextToType(WingTokenizer &Tok, FEdGraphPinType& OutPinType, con
|
||||
{
|
||||
if (OutPinType.PinCategory != Require.PinCategory)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Need a type which is an %s, got a %s instead.\n"),
|
||||
Errors.Printf(TEXT("ERROR: Need a type which is an %s, got a %s instead.\n"),
|
||||
*Require.PinCategory.ToString(), *OutPinType.PinCategory.ToString());
|
||||
UWingServer::SuggestManual(WingManual::Section::HandlerHelp);
|
||||
OutPinType = FEdGraphPinType(); return false;
|
||||
@@ -657,7 +657,7 @@ bool UWingTypes::TextToType(WingTokenizer &Tok, FEdGraphPinType& OutPinType, con
|
||||
{
|
||||
if (!IsChildOf(OutPinType, Require.IsChildOf))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Type must derive from %s\n"), *WingUtils::FormatName(Require.IsChildOf));
|
||||
Errors.Printf(TEXT("ERROR: Type must derive from %s\n"), *WingUtils::FormatName(Require.IsChildOf));
|
||||
UWingServer::SuggestManual(WingManual::Section::HandlerHelp);
|
||||
OutPinType = FEdGraphPinType(); return false;
|
||||
}
|
||||
@@ -668,7 +668,7 @@ bool UWingTypes::TextToType(WingTokenizer &Tok, FEdGraphPinType& OutPinType, con
|
||||
if (!IsBlueprintType(OutPinType))
|
||||
{
|
||||
FString Text(Tok.GetRange(NAME_StartOfType, 0));
|
||||
UWingServer::Printf(TEXT("ERROR: Not a blueprint type: %s\n"), *Text);
|
||||
Errors.Printf(TEXT("ERROR: Not a blueprint type: %s\n"), *Text);
|
||||
UWingServer::SuggestManual(WingManual::Section::HandlerHelp);
|
||||
OutPinType = FEdGraphPinType(); return false;
|
||||
}
|
||||
@@ -679,7 +679,7 @@ bool UWingTypes::TextToType(WingTokenizer &Tok, FEdGraphPinType& OutPinType, con
|
||||
if (!IsBlueprintable(OutPinType))
|
||||
{
|
||||
FString Text(Tok.GetRange(NAME_StartOfType, 0));
|
||||
UWingServer::Printf(TEXT("ERROR: Not a blueprintable type: %s\n"), *Text);
|
||||
Errors.Printf(TEXT("ERROR: Not a blueprintable type: %s\n"), *Text);
|
||||
UWingServer::SuggestManual(WingManual::Section::HandlerHelp);
|
||||
OutPinType = FEdGraphPinType(); return false;
|
||||
}
|
||||
@@ -688,36 +688,36 @@ bool UWingTypes::TextToType(WingTokenizer &Tok, FEdGraphPinType& OutPinType, con
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UWingTypes::TextToType(const FString &Text, FEdGraphPinType& OutPinType, const Requirements &Require)
|
||||
bool UWingTypes::TextToType(const FString &Text, FEdGraphPinType& OutPinType, const Requirements &Require, WingOut Errors)
|
||||
{
|
||||
WingTokenizer Tok(Text);
|
||||
return TextToType(Tok, OutPinType, Require, true);
|
||||
return TextToType(Tok, OutPinType, Require, true, Errors);
|
||||
}
|
||||
|
||||
UClass* UWingTypes::TextToOneObjectType(const FString& Text, const Requirements &Require)
|
||||
UClass* UWingTypes::TextToOneObjectType(const FString& Text, const Requirements &Require, WingOut Errors)
|
||||
{
|
||||
FEdGraphPinType PinType;
|
||||
if (!TextToType(Text, PinType, Require)) return nullptr;
|
||||
if (!TextToType(Text, PinType, Require, Errors)) return nullptr;
|
||||
UClass* Class = Cast<UClass>(PinType.PinSubCategoryObject.Get());
|
||||
if ((!Class) || (PinType.PinCategory != UEdGraphSchema_K2::PC_Object) ||
|
||||
(PinType.IsContainer()))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: '%s' is not an object class\n"), *Text);
|
||||
Errors.Printf(TEXT("ERROR: '%s' is not an object class\n"), *Text);
|
||||
UWingServer::SuggestManual(WingManual::Section::Types);
|
||||
return nullptr;
|
||||
}
|
||||
return Class;
|
||||
}
|
||||
|
||||
UClass* UWingTypes::TextToOneInterfaceType(const FString& Text, const Requirements &Require)
|
||||
UClass* UWingTypes::TextToOneInterfaceType(const FString& Text, const Requirements &Require, WingOut Errors)
|
||||
{
|
||||
FEdGraphPinType PinType;
|
||||
if (!TextToType(Text, PinType, Require)) return nullptr;
|
||||
if (!TextToType(Text, PinType, Require, Errors)) return nullptr;
|
||||
UClass* Class = Cast<UClass>(PinType.PinSubCategoryObject.Get());
|
||||
if ((!Class) || (PinType.PinCategory != UEdGraphSchema_K2::PC_Interface) ||
|
||||
(PinType.IsContainer()))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: '%s' is not an interface class\n"), *Text);
|
||||
Errors.Printf(TEXT("ERROR: '%s' is not an interface class\n"), *Text);
|
||||
UWingServer::SuggestManual(WingManual::Section::Types);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -61,24 +61,24 @@ FString WingUtils::ExternalizeID(FName Name)
|
||||
return WingTokenizer::ExternalizeID(Name);
|
||||
}
|
||||
|
||||
FName WingUtils::CheckInternalizeID(const FString &ExternalID)
|
||||
FName WingUtils::CheckInternalizeID(const FString &ExternalID, WingOut Errors)
|
||||
{
|
||||
FString Error;
|
||||
FName InternalID = WingTokenizer::TryInternalizeID(ExternalID, Error);
|
||||
if (!Error.IsEmpty())
|
||||
{
|
||||
UWingServer::Printf(TEXT("%s\n"), *Error);
|
||||
Errors.Printf(TEXT("%s\n"), *Error);
|
||||
UWingServer::SuggestManual(WingManual::Section::EscapeSequences);
|
||||
}
|
||||
return InternalID;
|
||||
}
|
||||
|
||||
FName WingUtils::CheckProposedName(const FString &ExternalID)
|
||||
FName WingUtils::CheckProposedName(const FString &ExternalID, WingOut Errors)
|
||||
{
|
||||
FName InternalID = CheckInternalizeID(ExternalID);
|
||||
FName InternalID = CheckInternalizeID(ExternalID, Errors);
|
||||
if (!InternalID.IsNone() && !WingTokenizer::WouldExternalizeReadably(InternalID))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: id %s would not be a readable id, may not create item with this name"),
|
||||
Errors.Printf(TEXT("ERROR: id %s would not be a readable id, may not create item with this name"),
|
||||
*ExternalID);
|
||||
UWingServer::SuggestManual(WingManual::Section::EscapeSequences);
|
||||
return FName();
|
||||
@@ -341,7 +341,7 @@ FString WingUtils::EnumToString(UEnum* Enum, int64 Value)
|
||||
return Enum->GetNameStringByValue(Value);
|
||||
}
|
||||
|
||||
bool WingUtils::StringToEnum(UEnum* Enum, const FString& Str, int64& OutValue)
|
||||
bool WingUtils::StringToEnum(UEnum* Enum, const FString& Str, int64& OutValue, WingOut Errors)
|
||||
{
|
||||
int32 Index = Enum->GetIndexByNameString(Str);
|
||||
if (Index == INDEX_NONE)
|
||||
@@ -352,7 +352,7 @@ bool WingUtils::StringToEnum(UEnum* Enum, const FString& Str, int64& OutValue)
|
||||
}
|
||||
if (Index == INDEX_NONE)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: '%s' is not a valid value for %s\n"), *Str, *Enum->GetName());
|
||||
Errors.Printf(TEXT("ERROR: '%s' is not a valid value for %s\n"), *Str, *Enum->GetName());
|
||||
OutValue = 0;
|
||||
return false;
|
||||
}
|
||||
@@ -365,53 +365,53 @@ bool WingUtils::StringToEnum(UEnum* Enum, const FString& Str, int64& OutValue)
|
||||
// Common Error Reporting
|
||||
// ============================================================
|
||||
|
||||
bool WingUtils::CheckExactlyOneNamed(int Count, const TCHAR *Kind, const FString &Name)
|
||||
bool WingUtils::CheckExactlyOneNamed(int Count, const TCHAR *Kind, const FString &Name, WingOut Errors)
|
||||
{
|
||||
if (Count == 0)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Could not find a %s named %s.\n"), Kind, *Name);
|
||||
Errors.Printf(TEXT("Could not find a %s named %s.\n"), Kind, *Name);
|
||||
return false;
|
||||
}
|
||||
if (Count > 1)
|
||||
{
|
||||
UWingServer::Printf(TEXT("More than one %s named %s\n"), Kind, *Name);
|
||||
Errors.Printf(TEXT("More than one %s named %s\n"), Kind, *Name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingUtils::CheckExactlyOneNamed(int Count, const TCHAR *Kind, FName Name)
|
||||
bool WingUtils::CheckExactlyOneNamed(int Count, const TCHAR *Kind, FName Name, WingOut Errors)
|
||||
{
|
||||
return CheckExactlyOneNamed(Count, Kind, ExternalizeID(Name));
|
||||
return CheckExactlyOneNamed(Count, Kind, ExternalizeID(Name), Errors);
|
||||
}
|
||||
|
||||
bool WingUtils::CheckExactlyNoneNamed(int Count, const TCHAR *Kind, const FString &Name)
|
||||
bool WingUtils::CheckExactlyNoneNamed(int Count, const TCHAR *Kind, const FString &Name, WingOut Errors)
|
||||
{
|
||||
if (Count > 0)
|
||||
{
|
||||
UWingServer::Printf(TEXT("A %s named %s already exists."), Kind, *Name);
|
||||
Errors.Printf(TEXT("A %s named %s already exists."), Kind, *Name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingUtils::CheckExactlyNoneNamed(int Count, const TCHAR *Kind, FName Name)
|
||||
bool WingUtils::CheckExactlyNoneNamed(int Count, const TCHAR *Kind, FName Name, WingOut Errors)
|
||||
{
|
||||
return CheckExactlyNoneNamed(Count, Kind, ExternalizeID(Name));
|
||||
return CheckExactlyNoneNamed(Count, Kind, ExternalizeID(Name), Errors);
|
||||
}
|
||||
|
||||
bool WingUtils::CheckCanRename(UEdGraphNode* Node, const FString &Name)
|
||||
bool WingUtils::CheckCanRename(UEdGraphNode* Node, const FString &Name, WingOut Errors)
|
||||
{
|
||||
if (!Node->bCanRenameNode)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Node %s does not support renaming.\n"), *FormatName(Node));
|
||||
Errors.Printf(TEXT("ERROR: Node %s does not support renaming.\n"), *FormatName(Node));
|
||||
return false;
|
||||
}
|
||||
TSharedPtr<INameValidatorInterface> Validator = FNameValidatorFactory::MakeValidator(Node);
|
||||
EValidatorResult Result = Validator->IsValid(Name, false);
|
||||
if (Result != EValidatorResult::Ok && Result != EValidatorResult::ExistingName)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: %s\n"), *INameValidatorInterface::GetErrorString(Name, Result));
|
||||
Errors.Printf(TEXT("ERROR: %s\n"), *INameValidatorInterface::GetErrorString(Name, Result));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -573,7 +573,7 @@ UAnimationStateMachineGraph* WingUtils::FindStateMachineGraph(UBlueprint* BP, co
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UAnimStateNode* WingUtils::FindStateByName(UAnimationStateMachineGraph* SMGraph, const FString& StateName)
|
||||
UAnimStateNode* WingUtils::FindStateByName(UAnimationStateMachineGraph* SMGraph, const FString& StateName, WingOut Errors)
|
||||
{
|
||||
for (UEdGraphNode* Node : SMGraph->Nodes)
|
||||
{
|
||||
@@ -585,7 +585,7 @@ UAnimStateNode* WingUtils::FindStateByName(UAnimationStateMachineGraph* SMGraph,
|
||||
}
|
||||
}
|
||||
}
|
||||
UWingServer::Printf(TEXT("ERROR: State '%s' not found in graph '%s'\n"), *StateName, *SMGraph->GetName());
|
||||
Errors.Printf(TEXT("ERROR: State '%s' not found in graph '%s'\n"), *StateName, *SMGraph->GetName());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,12 +26,12 @@ static TSet<FName> Flags_BlueprintVariables = { Flag_InstanceEditable, Flag_Blue
|
||||
|
||||
|
||||
|
||||
void WingVariableList::Print(FStringBuilderBase &Out)
|
||||
void WingVariableList::Print(WingOut Out)
|
||||
{
|
||||
if (Variables.IsEmpty()) return;
|
||||
Out.Append(ListName);
|
||||
Out.AppendChar(':');
|
||||
Out.AppendChar('\n');
|
||||
Out.Print(ListName);
|
||||
Out.PrintChar(':');
|
||||
Out.PrintChar('\n');
|
||||
for (const Var& V : Variables)
|
||||
{
|
||||
FString TypeStr = UWingTypes::TypeToText(V.Type);
|
||||
@@ -51,23 +51,23 @@ void WingVariableList::Print(FStringBuilderBase &Out)
|
||||
}
|
||||
|
||||
// Print: type name (flags) = defaultvalue
|
||||
Out.Appendf(TEXT(" %s %s"), *TypeStr, *NameStr);
|
||||
Out.Printf(TEXT(" %s %s"), *TypeStr, *NameStr);
|
||||
if (!FlagsStr.IsEmpty())
|
||||
Out.Appendf(TEXT(" (%s)"), *FlagsStr);
|
||||
Out.Printf(TEXT(" (%s)"), *FlagsStr);
|
||||
if (!V.DefaultValue.IsEmpty())
|
||||
Out.Appendf(TEXT(" = %s"), *V.DefaultValue);
|
||||
Out.Append(TEXT("\n"));
|
||||
Out.Printf(TEXT(" = %s"), *V.DefaultValue);
|
||||
Out.Print(TEXT("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
void WingVariableList::PrintCompact(FStringBuilderBase &Out)
|
||||
void WingVariableList::PrintCompact(WingOut Out)
|
||||
{
|
||||
bool First = true;
|
||||
for (const Var& V : Variables)
|
||||
{
|
||||
if (!First) Out << TEXT(",");
|
||||
if (!First) Out.PrintChar(',');
|
||||
First = false;
|
||||
Out << UWingTypes::TypeToText(V.Type) << TEXT(" ") << WingUtils::ExternalizeID(V.Name);
|
||||
Out.Printf(TEXT("%s %s"), *UWingTypes::TypeToText(V.Type), *WingUtils::ExternalizeID(V.Name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,11 +80,11 @@ void WingVariableList::ClearLinks()
|
||||
}
|
||||
}
|
||||
|
||||
bool WingVariableList::CheckSanity(const TSet<FName> &GoodFlags, bool Allow)
|
||||
bool WingVariableList::CheckSanity(const TSet<FName> &GoodFlags, bool Allow, WingOut Errors)
|
||||
{
|
||||
if ((!Allow) && (!Variables.IsEmpty()))
|
||||
{
|
||||
UWingServer::Printf(TEXT("In this context, %s must be empty."), ListName);
|
||||
Errors.Printf(TEXT("In this context, %s must be empty."), ListName);
|
||||
return false;
|
||||
}
|
||||
for (const Var &Variable : Variables)
|
||||
@@ -93,20 +93,20 @@ bool WingVariableList::CheckSanity(const TSet<FName> &GoodFlags, bool Allow)
|
||||
FString TypeText = UWingTypes::TypeToText(Variable.Type);
|
||||
if (TypeText.IsEmpty())
|
||||
{
|
||||
UWingServer::Printf(TEXT("Type of variable %s is not valid for unknown reasons\n"), *VarName);
|
||||
Errors.Printf(TEXT("Type of variable %s is not valid for unknown reasons\n"), *VarName);
|
||||
return false;
|
||||
}
|
||||
if (!UWingTypes::IsBlueprintType(Variable.Type))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Type is not a valid BlueprintType: %s %s\n"), *TypeText, *VarName);
|
||||
Errors.Printf(TEXT("Type is not a valid BlueprintType: %s %s\n"), *TypeText, *VarName);
|
||||
return false;
|
||||
}
|
||||
for (FName Flag : Variable.Flags)
|
||||
{
|
||||
if (!GoodFlags.Contains(Flag))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Flag %s is not valid here. Valid flags are:"), *Flag.ToString());
|
||||
for (FName Rel : GoodFlags) UWingServer::Printf(TEXT(" %s\n"), *Rel.ToString());
|
||||
Errors.Printf(TEXT("Flag %s is not valid here. Valid flags are:"), *Flag.ToString());
|
||||
for (FName Rel : GoodFlags) Errors.Printf(TEXT(" %s\n"), *Rel.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ bool WingVariableList::CheckSanity(const TSet<FName> &GoodFlags, bool Allow)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingVariableList::ParseString(const FString &Input)
|
||||
bool WingVariableList::ParseString(const FString &Input, WingOut Errors)
|
||||
{
|
||||
Variables.Empty();
|
||||
|
||||
@@ -127,14 +127,14 @@ bool WingVariableList::ParseString(const FString &Input)
|
||||
if (Tok.NextType() == 0) continue;
|
||||
Var V;
|
||||
V.DefaultSpecified = false;
|
||||
if (!ParseOneVariable(Tok, V)) return false;
|
||||
if (!ParseOneVariable(Tok, V, Errors)) return false;
|
||||
Variables.Add(MoveTemp(V));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingVariableList::ParseNamesString(const FString &Input)
|
||||
bool WingVariableList::ParseNamesString(const FString &Input, WingOut Errors)
|
||||
{
|
||||
Variables.Empty();
|
||||
WingTokenizer Tok(Input);
|
||||
@@ -151,27 +151,27 @@ bool WingVariableList::ParseNamesString(const FString &Input)
|
||||
if (!Tok.TokenIs(0))
|
||||
{
|
||||
Tok.SaveCursor(NAME_None);
|
||||
UWingServer::Printf(TEXT("Unexpected token %s in variable list"),
|
||||
Errors.Printf(TEXT("Unexpected token %s in variable list"),
|
||||
*FString(Tok.GetRange(NAME_None, 1)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingVariableList::ParseOneVariable(WingTokenizer &Tok, Var &V)
|
||||
bool WingVariableList::ParseOneVariable(WingTokenizer &Tok, Var &V, WingOut Errors)
|
||||
{
|
||||
// Parse type.
|
||||
UWingTypes::Requirements Req;
|
||||
Req.BlueprintType = true;
|
||||
Req.Blueprintable = false;
|
||||
Req.AllowContainer = true;
|
||||
if (!UWingTypes::TextToType(Tok, V.Type, Req, false))
|
||||
if (!UWingTypes::TextToType(Tok, V.Type, Req, false, Errors))
|
||||
return false;
|
||||
|
||||
// Parse name.
|
||||
if (Tok.NextType() != Tok.Identifier)
|
||||
{
|
||||
UWingServer::Print(TEXT("ERROR: Expected variable name after type\n"));
|
||||
Errors.Print(TEXT("ERROR: Expected variable name after type\n"));
|
||||
return false;
|
||||
}
|
||||
V.Name = Tok.NextName();
|
||||
@@ -180,7 +180,7 @@ bool WingVariableList::ParseOneVariable(WingTokenizer &Tok, Var &V)
|
||||
// Parse optional flags: (flag1, flag2, ...)
|
||||
if (Tok.TokenIs('('))
|
||||
{
|
||||
if (!ParseVariableFlags(Tok, V.Flags)) return false;
|
||||
if (!ParseVariableFlags(Tok, V.Flags, Errors)) return false;
|
||||
}
|
||||
|
||||
// Parse optional default value: = rest-of-line
|
||||
@@ -195,7 +195,7 @@ bool WingVariableList::ParseOneVariable(WingTokenizer &Tok, Var &V)
|
||||
if (Tok.NextType() != 0)
|
||||
{
|
||||
Tok.SaveCursor(NAME_None);
|
||||
UWingServer::Printf(TEXT("ERROR: Unexpected token after variable declaration: '%s'\n"),
|
||||
Errors.Printf(TEXT("ERROR: Unexpected token after variable declaration: '%s'\n"),
|
||||
*FString(Tok.GetRange(NAME_None, 1)));
|
||||
return false;
|
||||
}
|
||||
@@ -203,7 +203,7 @@ bool WingVariableList::ParseOneVariable(WingTokenizer &Tok, Var &V)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingVariableList::ParseVariableFlags(WingTokenizer &Tok, TSet<FName> &Out)
|
||||
bool WingVariableList::ParseVariableFlags(WingTokenizer &Tok, TSet<FName> &Out, WingOut Errors)
|
||||
{
|
||||
Tok.Advance(); // Step over open-paren
|
||||
while (Tok.TokenIs(Tok.Identifier))
|
||||
@@ -216,7 +216,7 @@ bool WingVariableList::ParseVariableFlags(WingTokenizer &Tok, TSet<FName> &Out)
|
||||
if (!Tok.TokenIs(')'))
|
||||
{
|
||||
Tok.SaveCursor(NAME_None);
|
||||
UWingServer::Printf(TEXT("ERROR: flag list contains invalid token '%s'\n"),
|
||||
Errors.Printf(TEXT("ERROR: flag list contains invalid token '%s'\n"),
|
||||
*FString(Tok.GetRange(NAME_None, 1)));
|
||||
return false;
|
||||
}
|
||||
@@ -240,7 +240,7 @@ void WingVariables::ClearLinks()
|
||||
OutputVariables.ClearLinks();
|
||||
}
|
||||
|
||||
void WingVariables::Print(FStringBuilderBase &Out)
|
||||
void WingVariables::Print(WingOut Out)
|
||||
{
|
||||
BlueprintVariables.Print(Out);
|
||||
LocalVariables.Print(Out);
|
||||
@@ -248,13 +248,13 @@ void WingVariables::Print(FStringBuilderBase &Out)
|
||||
OutputVariables.Print(Out);
|
||||
}
|
||||
|
||||
void WingVariables::Load()
|
||||
void WingVariables::Load(WingOut Errors)
|
||||
{
|
||||
Empty();
|
||||
if (Blueprint != nullptr) return LoadBlueprint();
|
||||
if (Graph != nullptr) return LoadGraph();
|
||||
if (CustomEvent != nullptr) return LoadCustomEvent();
|
||||
ErrorNoBackingStore();
|
||||
ErrorNoBackingStore(Errors);
|
||||
}
|
||||
|
||||
void WingVariables::LoadBlueprint()
|
||||
@@ -356,25 +356,25 @@ void WingVariables::LoadCustomEvent()
|
||||
LoadEditablePinBase(CustomEvent, InputVariables);
|
||||
}
|
||||
|
||||
bool WingVariables::Check()
|
||||
bool WingVariables::Check(WingOut Errors)
|
||||
{
|
||||
if (Blueprint) return CheckBlueprint();
|
||||
if (Graph) return CheckGraph();
|
||||
if (CustomEvent) return CheckCustomEvent();
|
||||
return ErrorNoBackingStore();
|
||||
if (Blueprint) return CheckBlueprint(Errors);
|
||||
if (Graph) return CheckGraph(Errors);
|
||||
if (CustomEvent) return CheckCustomEvent(Errors);
|
||||
return ErrorNoBackingStore(Errors);
|
||||
}
|
||||
|
||||
bool WingVariables::CheckBlueprint()
|
||||
bool WingVariables::CheckBlueprint(WingOut Errors)
|
||||
{
|
||||
bool OK = true;
|
||||
if (!BlueprintVariables.CheckSanity(Flags_BlueprintVariables, true)) OK = false;
|
||||
if (!LocalVariables.CheckSanity(Flags_None, false)) OK = false;
|
||||
if (!InputVariables.CheckSanity(Flags_None, false)) OK = false;
|
||||
if (!OutputVariables.CheckSanity(Flags_None, false)) OK = false;
|
||||
if (!BlueprintVariables.CheckSanity(Flags_BlueprintVariables, true, Errors)) OK = false;
|
||||
if (!LocalVariables.CheckSanity(Flags_None, false, Errors)) OK = false;
|
||||
if (!InputVariables.CheckSanity(Flags_None, false, Errors)) OK = false;
|
||||
if (!OutputVariables.CheckSanity(Flags_None, false, Errors)) OK = false;
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool WingVariables::CheckGraph()
|
||||
bool WingVariables::CheckGraph(WingOut Errors)
|
||||
{
|
||||
EGraphType T = Graph->GetSchema()->GetGraphType(Graph);
|
||||
bool AllowLocal = (T == EGraphType::GT_Function);
|
||||
@@ -382,56 +382,56 @@ bool WingVariables::CheckGraph()
|
||||
bool AllowOutput = (T == EGraphType::GT_Function) || (T == EGraphType::GT_Macro);
|
||||
if ((!AllowLocal) && (!AllowInput) && (!AllowOutput))
|
||||
{
|
||||
UWingServer::Printf(TEXT("This graph type has no variables."));
|
||||
Errors.Printf(TEXT("This graph type has no variables."));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OK = true;
|
||||
if (!BlueprintVariables.CheckSanity(Flags_None, false)) OK = false;
|
||||
if (!LocalVariables.CheckSanity(Flags_None, AllowLocal)) OK = false;
|
||||
if (!InputVariables.CheckSanity(Flags_None, AllowInput)) OK = false;
|
||||
if (!OutputVariables.CheckSanity(Flags_None, AllowOutput)) OK = false;
|
||||
if (!BlueprintVariables.CheckSanity(Flags_None, false, Errors)) OK = false;
|
||||
if (!LocalVariables.CheckSanity(Flags_None, AllowLocal, Errors)) OK = false;
|
||||
if (!InputVariables.CheckSanity(Flags_None, AllowInput, Errors)) OK = false;
|
||||
if (!OutputVariables.CheckSanity(Flags_None, AllowOutput, Errors)) OK = false;
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool WingVariables::CheckCustomEvent()
|
||||
bool WingVariables::CheckCustomEvent(WingOut Errors)
|
||||
{
|
||||
bool OK = true;
|
||||
if (!BlueprintVariables.CheckSanity(Flags_None, false)) OK = false;
|
||||
if (!LocalVariables.CheckSanity(Flags_None, false)) OK = false;
|
||||
if (!InputVariables.CheckSanity(Flags_None, true)) OK = false;
|
||||
if (!OutputVariables.CheckSanity(Flags_None, false)) OK = false;
|
||||
if (!BlueprintVariables.CheckSanity(Flags_None, false, Errors)) OK = false;
|
||||
if (!LocalVariables.CheckSanity(Flags_None, false, Errors)) OK = false;
|
||||
if (!InputVariables.CheckSanity(Flags_None, true, Errors)) OK = false;
|
||||
if (!OutputVariables.CheckSanity(Flags_None, false, Errors)) OK = false;
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool WingVariables::Modify()
|
||||
bool WingVariables::Modify(WingOut Errors)
|
||||
{
|
||||
if (Blueprint) return ModifyBlueprint();
|
||||
if (Graph) return ModifyGraph();
|
||||
if (CustomEvent) return ModifyCustomEvent();
|
||||
return ErrorNoBackingStore();
|
||||
if (Blueprint) return ModifyBlueprint(Errors);
|
||||
if (Graph) return ModifyGraph(Errors);
|
||||
if (CustomEvent) return ModifyCustomEvent(Errors);
|
||||
return ErrorNoBackingStore(Errors);
|
||||
}
|
||||
|
||||
bool WingVariables::ModifyBlueprint()
|
||||
bool WingVariables::ModifyBlueprint(WingOut Errors)
|
||||
{
|
||||
if (!CheckBlueprint()) return false;
|
||||
if (LinkBlueprintVariables()) return false;
|
||||
for (Var &V : BlueprintVariables.Variables)
|
||||
if (!CheckBlueprint(Errors)) return false;
|
||||
if (LinkBlueprintVariables(Errors)) return false;
|
||||
for (Var &V : BlueprintVariables.Variables)
|
||||
{
|
||||
V.BPVar->VarType = V.Type;
|
||||
ModifyBlueprintVariableFlags(V);
|
||||
}
|
||||
if (!ModifyBlueprintDefaults()) return false;
|
||||
if (!ModifyBlueprintDefaults(Errors)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingVariables::LinkBlueprintVariables()
|
||||
bool WingVariables::LinkBlueprintVariables(WingOut Errors)
|
||||
{
|
||||
ClearLinks();
|
||||
for (Var &V : BlueprintVariables.Variables)
|
||||
{
|
||||
V.BPVar = WingUtils::FindOneWithInternalID(
|
||||
V.Name, Blueprint->NewVariables, TEXT("non-inherited variable"));
|
||||
V.Name, Blueprint->NewVariables, TEXT("non-inherited variable"), Errors);
|
||||
if (V.BPVar == nullptr) return false;
|
||||
}
|
||||
return true;
|
||||
@@ -468,7 +468,7 @@ void WingVariables::ModifyBlueprintVariableFlags(Var &Input)
|
||||
Out.RemoveMetaData(FBlueprintMetadata::MD_Private);
|
||||
}
|
||||
|
||||
bool WingVariables::ModifyBlueprintDefaults()
|
||||
bool WingVariables::ModifyBlueprintDefaults(WingOut Errors)
|
||||
{
|
||||
bool AnySpecified = false;
|
||||
for (Var &Input : BlueprintVariables.Variables)
|
||||
@@ -479,7 +479,7 @@ bool WingVariables::ModifyBlueprintDefaults()
|
||||
UObject *CDO = WingUtils::GetGeneratedCDO(Blueprint);
|
||||
if (!CDO)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Blueprint didn't compile, cannot store default values"));
|
||||
Errors.Printf(TEXT("Blueprint didn't compile, cannot store default values"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -490,56 +490,56 @@ bool WingVariables::ModifyBlueprintDefaults()
|
||||
FProperty* Prop = CDO->GetClass()->FindPropertyByName(Input.Name);
|
||||
if (!Prop)
|
||||
{
|
||||
UWingServer::Printf(TEXT("Variable exists in blueprint, but not the generated class, which is weird: %s."),
|
||||
Errors.Printf(TEXT("Variable exists in blueprint, but not the generated class, which is weird: %s."),
|
||||
*WingTokenizer::ExternalizeID(Input.Name));
|
||||
return false;
|
||||
}
|
||||
if (!FWingProperty(Prop, CDO).SetText(Input.DefaultValue)) return false;
|
||||
if (!FWingProperty(Prop, CDO).SetText(Input.DefaultValue, Errors)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingVariables::ModifyGraph()
|
||||
bool WingVariables::ModifyGraph(WingOut Errors)
|
||||
{
|
||||
if (!CheckGraph()) return false;
|
||||
if (!CheckGraph(Errors)) return false;
|
||||
ClearLinks();
|
||||
|
||||
UK2Node_EditablePinBase *InputNode, *OutputNode;
|
||||
UK2Node_FunctionEntry *LocalNode;
|
||||
if (!GetGraphNodes(InputNode, OutputNode, LocalNode)) return false;
|
||||
if (!GetGraphNodes(InputNode, OutputNode, LocalNode, Errors)) return false;
|
||||
|
||||
for (Var &V : LocalVariables.Variables)
|
||||
{
|
||||
FBPVariableDescription *Desc =
|
||||
WingUtils::FindOneWithInternalID(V.Name, LocalNode->LocalVariables, TEXT("local variable"));
|
||||
WingUtils::FindOneWithInternalID(V.Name, LocalNode->LocalVariables, TEXT("local variable"), Errors);
|
||||
if (Desc == nullptr) return false;
|
||||
Desc->VarType = V.Type;
|
||||
if (V.DefaultSpecified) Desc->DefaultValue = V.DefaultValue;
|
||||
}
|
||||
if (!ModifyEditablePinBase(InputVariables, InputNode)) return false;
|
||||
if (!ModifyEditablePinBase(OutputVariables, OutputNode)) return false;
|
||||
if (!ModifyEditablePinBase(InputVariables, InputNode, Errors)) return false;
|
||||
if (!ModifyEditablePinBase(OutputVariables, OutputNode, Errors)) return false;
|
||||
|
||||
if (InputNode) InputNode->ReconstructNode();
|
||||
if (OutputNode) OutputNode->ReconstructNode();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingVariables::ModifyCustomEvent()
|
||||
bool WingVariables::ModifyCustomEvent(WingOut Errors)
|
||||
{
|
||||
if (!CheckCustomEvent()) return false;
|
||||
if (!CheckCustomEvent(Errors)) return false;
|
||||
ClearLinks();
|
||||
if (!ModifyEditablePinBase(InputVariables, CustomEvent)) return false;
|
||||
if (!ModifyEditablePinBase(InputVariables, CustomEvent, Errors)) return false;
|
||||
CustomEvent->ReconstructNode();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingVariables::ModifyEditablePinBase(WingVariableList &List, UK2Node_EditablePinBase *Node)
|
||||
bool WingVariables::ModifyEditablePinBase(WingVariableList &List, UK2Node_EditablePinBase *Node, WingOut Errors)
|
||||
{
|
||||
for (Var &V : List.Variables)
|
||||
{
|
||||
TSharedPtr<FUserPinInfo> *Found =
|
||||
WingUtils::FindOneWithInternalID(V.Name, Node->UserDefinedPins, List.ListName);
|
||||
WingUtils::FindOneWithInternalID(V.Name, Node->UserDefinedPins, List.ListName, Errors);
|
||||
if (!Found) return false;
|
||||
(*Found)->PinType = V.Type;
|
||||
if (V.DefaultSpecified) (*Found)->PinDefaultValue = V.DefaultValue;
|
||||
@@ -550,7 +550,8 @@ bool WingVariables::ModifyEditablePinBase(WingVariableList &List, UK2Node_Editab
|
||||
bool WingVariables::GetGraphNodes(
|
||||
UK2Node_EditablePinBase *&InputNode,
|
||||
UK2Node_EditablePinBase *&OutputNode,
|
||||
UK2Node_FunctionEntry *&LocalNode)
|
||||
UK2Node_FunctionEntry *&LocalNode,
|
||||
WingOut Errors)
|
||||
{
|
||||
// In theory, none of these errors should trigger, because
|
||||
// we call CheckSanity before calling this function. But
|
||||
@@ -563,22 +564,22 @@ bool WingVariables::GetGraphNodes(
|
||||
FBlueprintEditorUtils::GetEntryAndResultNodes(Graph, Inputs, Outputs);
|
||||
if (!Inputs.IsValid())
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: no function entry node for graph."));
|
||||
Errors.Printf(TEXT("ERROR: no function entry node for graph."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!Outputs.IsValid() && (!OutputVariables.Variables.IsEmpty()))
|
||||
{
|
||||
Outputs = FBlueprintEditorUtils::FindOrCreateFunctionResultNode(Inputs.Get());
|
||||
if (!Outputs.IsValid())
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: couldn't create result node for graph."));
|
||||
Errors.Printf(TEXT("ERROR: couldn't create result node for graph."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
UK2Node_FunctionEntry *Locals = Cast<UK2Node_FunctionEntry>(Inputs.Get());
|
||||
if (!Locals && (!LocalVariables.Variables.IsEmpty()))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: function doesn't have a proper entry node for local variables"));
|
||||
Errors.Printf(TEXT("ERROR: function doesn't have a proper entry node for local variables"));
|
||||
return false;
|
||||
}
|
||||
InputNode = Inputs.Get();
|
||||
@@ -587,65 +588,65 @@ bool WingVariables::GetGraphNodes(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingVariables::Create()
|
||||
bool WingVariables::Create(WingOut Errors)
|
||||
{
|
||||
if (Blueprint) return CreateBlueprint();
|
||||
if (Graph) return CreateGraph();
|
||||
if (CustomEvent) return CreateCustomEvent();
|
||||
return ErrorNoBackingStore();
|
||||
if (Blueprint) return CreateBlueprint(Errors);
|
||||
if (Graph) return CreateGraph(Errors);
|
||||
if (CustomEvent) return CreateCustomEvent(Errors);
|
||||
return ErrorNoBackingStore(Errors);
|
||||
}
|
||||
|
||||
bool WingVariables::CreateBlueprint()
|
||||
bool WingVariables::CreateBlueprint(WingOut Errors)
|
||||
{
|
||||
if (!CheckBlueprint()) return false;
|
||||
if (!CheckBlueprint(Errors)) return false;
|
||||
ClearLinks();
|
||||
|
||||
// Check for name collisions against existing variables, components, and the like.
|
||||
TSet<FName> Names;
|
||||
FBlueprintEditorUtils::GetClassVariableList(Blueprint, Names);
|
||||
if (!WingUtils::FindNoDuplicateNames(Names, BlueprintVariables.Variables, TEXT("variable or component"))) return false;
|
||||
if (!WingUtils::FindNoDuplicateNames(Names, BlueprintVariables.Variables, TEXT("variable or component"), Errors)) return false;
|
||||
|
||||
// Create the variables.
|
||||
for (const WingVariables::Var& V : BlueprintVariables.Variables)
|
||||
{
|
||||
if (!FBlueprintEditorUtils::AddMemberVariable(Blueprint, V.Name, V.Type))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to add variable '%s'\n"),
|
||||
Errors.Printf(TEXT("ERROR: Failed to add variable '%s'\n"),
|
||||
*WingUtils::ExternalizeID(V.Name));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (LinkBlueprintVariables()) return false;
|
||||
if (LinkBlueprintVariables(Errors)) return false;
|
||||
for (Var &V : BlueprintVariables.Variables) ModifyBlueprintVariableFlags(V);
|
||||
if (!ModifyBlueprintDefaults()) return false;
|
||||
if (!ModifyBlueprintDefaults(Errors)) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WingVariables::CreateGraph()
|
||||
bool WingVariables::CreateGraph(WingOut Errors)
|
||||
{
|
||||
if (!CheckGraph()) return false;
|
||||
if (!CheckGraph(Errors)) return false;
|
||||
ClearLinks();
|
||||
|
||||
UK2Node_EditablePinBase *InputNode, *OutputNode;
|
||||
UK2Node_FunctionEntry *LocalNode;
|
||||
if (!GetGraphNodes(InputNode, OutputNode, LocalNode)) return false;
|
||||
if (!GetGraphNodes(InputNode, OutputNode, LocalNode, Errors)) return false;
|
||||
|
||||
// Check for name collisions against existing local variables.
|
||||
const TCHAR *ctx = TEXT("local, function input, and function output variables");
|
||||
TSet<FName> Names;
|
||||
if (InputNode && !WingUtils::FindNoDuplicateNames(
|
||||
Names, InputNode->UserDefinedPins, ctx)) return false;
|
||||
Names, InputNode->UserDefinedPins, ctx, Errors)) return false;
|
||||
if (OutputNode && !WingUtils::FindNoDuplicateNames(
|
||||
Names, OutputNode->UserDefinedPins, ctx)) return false;
|
||||
Names, OutputNode->UserDefinedPins, ctx, Errors)) return false;
|
||||
if (LocalNode && !WingUtils::FindNoDuplicateNames(
|
||||
Names, LocalNode->LocalVariables, ctx)) return false;
|
||||
Names, LocalNode->LocalVariables, ctx, Errors)) return false;
|
||||
if (!WingUtils::FindNoDuplicateNames(
|
||||
Names, InputVariables.Variables, ctx)) return false;
|
||||
Names, InputVariables.Variables, ctx, Errors)) return false;
|
||||
if (!WingUtils::FindNoDuplicateNames(
|
||||
Names, OutputVariables.Variables, ctx)) return false;
|
||||
Names, OutputVariables.Variables, ctx, Errors)) return false;
|
||||
if (!WingUtils::FindNoDuplicateNames(
|
||||
Names, LocalVariables.Variables, ctx)) return false;
|
||||
Names, LocalVariables.Variables, ctx, Errors)) return false;
|
||||
|
||||
// Create input pins on the input node.
|
||||
for (const Var& V : InputVariables.Variables)
|
||||
@@ -661,7 +662,7 @@ bool WingVariables::CreateGraph()
|
||||
{
|
||||
if (!FBlueprintEditorUtils::AddLocalVariable(BP, Graph, V.Name, V.Type, V.DefaultValue))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Failed to create local variable '%s'\n"),
|
||||
Errors.Printf(TEXT("ERROR: Failed to create local variable '%s'\n"),
|
||||
*WingUtils::ExternalizeID(V.Name));
|
||||
return false;
|
||||
}
|
||||
@@ -672,17 +673,17 @@ bool WingVariables::CreateGraph()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingVariables::CreateCustomEvent()
|
||||
bool WingVariables::CreateCustomEvent(WingOut Errors)
|
||||
{
|
||||
if (!CheckCustomEvent()) return false;
|
||||
if (!CheckCustomEvent(Errors)) return false;
|
||||
ClearLinks();
|
||||
|
||||
// Check for name collisions against existing pins.
|
||||
TSet<FName> Names;
|
||||
if (!WingUtils::FindNoDuplicateNames(
|
||||
Names, CustomEvent->UserDefinedPins, TEXT("event parameter"))) return false;
|
||||
Names, CustomEvent->UserDefinedPins, TEXT("event parameter"), Errors)) return false;
|
||||
if (!WingUtils::FindNoDuplicateNames(
|
||||
Names, InputVariables.Variables, TEXT("event parameter"))) return false;
|
||||
Names, InputVariables.Variables, TEXT("event parameter"), Errors)) return false;
|
||||
|
||||
for (const Var& V : InputVariables.Variables)
|
||||
AddUserPinInfo(V, EGPD_Output, CustomEvent);
|
||||
@@ -701,22 +702,22 @@ void WingVariables::AddUserPinInfo(const Var &V, EEdGraphPinDirection Dir, UK2No
|
||||
Node->UserDefinedPins.Add(Result);
|
||||
}
|
||||
|
||||
bool WingVariables::Remove()
|
||||
bool WingVariables::Remove(WingOut Errors)
|
||||
{
|
||||
if (Blueprint) return RemoveBlueprint();
|
||||
if (Graph) return RemoveGraph();
|
||||
if (CustomEvent) return RemoveCustomEvent();
|
||||
return ErrorNoBackingStore();
|
||||
if (Blueprint) return RemoveBlueprint(Errors);
|
||||
if (Graph) return RemoveGraph(Errors);
|
||||
if (CustomEvent) return RemoveCustomEvent(Errors);
|
||||
return ErrorNoBackingStore(Errors);
|
||||
}
|
||||
|
||||
bool WingVariables::RemoveBlueprint()
|
||||
bool WingVariables::RemoveBlueprint(WingOut Errors)
|
||||
{
|
||||
// Verify that all named variables exist.
|
||||
TArray<FName> Names;
|
||||
for (const Var& V : BlueprintVariables.Variables)
|
||||
{
|
||||
FBPVariableDescription* Found =
|
||||
WingUtils::FindOneWithInternalID(V.Name, Blueprint->NewVariables, TEXT("non-inherited variable"));
|
||||
WingUtils::FindOneWithInternalID(V.Name, Blueprint->NewVariables, TEXT("non-inherited variable"), Errors);
|
||||
if (!Found) return false;
|
||||
Names.Add(V.Name);
|
||||
}
|
||||
@@ -726,29 +727,29 @@ bool WingVariables::RemoveBlueprint()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingVariables::RemoveGraph()
|
||||
bool WingVariables::RemoveGraph(WingOut Errors)
|
||||
{
|
||||
UK2Node_EditablePinBase *InputNode, *OutputNode;
|
||||
UK2Node_FunctionEntry *LocalNode;
|
||||
if (!GetGraphNodes(InputNode, OutputNode, LocalNode)) return false;
|
||||
if (!GetGraphNodes(InputNode, OutputNode, LocalNode, Errors)) return false;
|
||||
|
||||
// Verify that all named variables exist before removing anything.
|
||||
for (const Var& V : InputVariables.Variables)
|
||||
{
|
||||
TSharedPtr<FUserPinInfo>* Found =
|
||||
WingUtils::FindOneWithInternalID(V.Name, InputNode->UserDefinedPins, TEXT("input variable"));
|
||||
WingUtils::FindOneWithInternalID(V.Name, InputNode->UserDefinedPins, TEXT("input variable"), Errors);
|
||||
if (!Found) return false;
|
||||
}
|
||||
for (const Var& V : OutputVariables.Variables)
|
||||
{
|
||||
TSharedPtr<FUserPinInfo>* Found =
|
||||
WingUtils::FindOneWithInternalID(V.Name, OutputNode->UserDefinedPins, TEXT("output variable"));
|
||||
WingUtils::FindOneWithInternalID(V.Name, OutputNode->UserDefinedPins, TEXT("output variable"), Errors);
|
||||
if (!Found) return false;
|
||||
}
|
||||
for (const Var& V : LocalVariables.Variables)
|
||||
{
|
||||
FBPVariableDescription* Found =
|
||||
WingUtils::FindOneWithInternalID(V.Name, LocalNode->LocalVariables, TEXT("local variable"));
|
||||
WingUtils::FindOneWithInternalID(V.Name, LocalNode->LocalVariables, TEXT("local variable"), Errors);
|
||||
if (!Found) return false;
|
||||
}
|
||||
|
||||
@@ -772,13 +773,13 @@ bool WingVariables::RemoveGraph()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingVariables::RemoveCustomEvent()
|
||||
bool WingVariables::RemoveCustomEvent(WingOut Errors)
|
||||
{
|
||||
// Verify that all named parameters exist before removing anything.
|
||||
for (const Var& V : InputVariables.Variables)
|
||||
{
|
||||
TSharedPtr<FUserPinInfo>* Found =
|
||||
WingUtils::FindOneWithInternalID(V.Name, CustomEvent->UserDefinedPins, TEXT("event parameter"));
|
||||
WingUtils::FindOneWithInternalID(V.Name, CustomEvent->UserDefinedPins, TEXT("event parameter"), Errors);
|
||||
if (!Found) return false;
|
||||
}
|
||||
|
||||
@@ -789,7 +790,7 @@ bool WingVariables::RemoveCustomEvent()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingVariables::SetBackingStore(UObject *Obj)
|
||||
bool WingVariables::SetBackingStore(UObject *Obj, WingOut Errors)
|
||||
{
|
||||
Blueprint = nullptr;
|
||||
Graph = nullptr;
|
||||
@@ -809,16 +810,16 @@ bool WingVariables::SetBackingStore(UObject *Obj)
|
||||
CustomEvent = E;
|
||||
return true;
|
||||
}
|
||||
UWingServer::Printf(TEXT(
|
||||
Errors.Printf(TEXT(
|
||||
"ERROR: The variable editor can only edit blueprints, "
|
||||
"graphs, and custom event nodes. Passed in: %s"),
|
||||
*WingUtils::FormatName(Obj->GetClass()));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WingVariables::ErrorNoBackingStore()
|
||||
bool WingVariables::ErrorNoBackingStore(WingOut Errors)
|
||||
{
|
||||
UWingServer::Printf(TEXT(
|
||||
Errors.Printf(TEXT(
|
||||
"ERROR: The variable editor was not successfully "
|
||||
"set up with an object to edit."));
|
||||
return false;
|
||||
|
||||
@@ -90,17 +90,17 @@ TArray<WingWidgets::Type> WingWidgets::Search(const FString& Query, int32 MaxRes
|
||||
return Results;
|
||||
}
|
||||
|
||||
bool WingWidgets::CheckCanBeParent(UWidget* Widget)
|
||||
bool WingWidgets::CheckCanBeParent(UWidget* Widget, WingOut Errors)
|
||||
{
|
||||
UPanelWidget* Panel = Cast<UPanelWidget>(Widget);
|
||||
if (!Panel)
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: '%s' is not a panel widget and cannot have children\n"), *WingUtils::FormatName(Widget));
|
||||
Errors.Printf(TEXT("ERROR: '%s' is not a panel widget and cannot have children\n"), *WingUtils::FormatName(Widget));
|
||||
return false;
|
||||
}
|
||||
if (!Panel->CanAddMoreChildren())
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: '%s' already has a child and cannot accept more\n"), *WingUtils::FormatName(Widget));
|
||||
Errors.Printf(TEXT("ERROR: '%s' already has a child and cannot accept more\n"), *WingUtils::FormatName(Widget));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -111,12 +111,12 @@ void WingWidgets::PrintWidgetTree(UWidget* Widget, int32 Depth)
|
||||
FString Indent = FString::ChrN(Depth * 2, TEXT(' '));
|
||||
if (Widget == nullptr)
|
||||
{
|
||||
UWingServer::Printf(TEXT("%s[null]\n"), *Indent);
|
||||
WingOut::Stdout.Printf(TEXT("%s[null]\n"), *Indent);
|
||||
return;
|
||||
}
|
||||
FString TypeName = WingUtils::FormatName(Widget->GetClass());
|
||||
FString WidgetName = WingUtils::FormatName(Widget);
|
||||
UWingServer::Printf(TEXT("%s%s %s\n"), *Indent, *TypeName, *WidgetName);
|
||||
WingOut::Stdout.Printf(TEXT("%s%s %s\n"), *Indent, *TypeName, *WidgetName);
|
||||
|
||||
if (UPanelWidget* Panel = Cast<UPanelWidget>(Widget))
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingActorComponent.generated.h"
|
||||
|
||||
class UBlueprint;
|
||||
@@ -41,13 +42,13 @@ public:
|
||||
UActorComponent* GetImmutableTemplate() const;
|
||||
UActorComponent* GetMutableTemplate() const;
|
||||
|
||||
bool ReparentComponent(UWingComponentReference *Parent);
|
||||
bool DeleteComponent();
|
||||
static bool AddComponent(UBlueprint *BP, UClass *Class, UWingComponentReference *Parent, FName Name);
|
||||
bool ReparentComponent(UWingComponentReference *Parent, WingOut Errors);
|
||||
bool DeleteComponent(WingOut Errors);
|
||||
static bool AddComponent(UBlueprint *BP, UClass *Class, UWingComponentReference *Parent, FName Name, WingOut Errors);
|
||||
|
||||
static TArray<UWingComponentReference*> GetAll(UBlueprint* BP);
|
||||
|
||||
static bool CheckValidComponentClass(UClass *Class);
|
||||
static bool CheckValidComponentClass(UClass *Class, WingOut Errors);
|
||||
private:
|
||||
struct FoundComponent
|
||||
{
|
||||
@@ -59,11 +60,11 @@ private:
|
||||
static UActorComponent *FindComponentInCDO(UClass *Class, FName Name);
|
||||
static USCS_Node* FindSCSNodeByName(UBlueprint *BP, FName VariableName);
|
||||
static FoundComponent FindComponent(UBlueprint *BP, FName Name);
|
||||
static bool CheckValidParent(FoundComponent FC);
|
||||
static bool CheckExists(FoundComponent FC);
|
||||
static bool CheckNoSuchComponent(FoundComponent FC);
|
||||
static bool CheckNotNative(FoundComponent FC, const TCHAR *Action);
|
||||
static bool CheckOwnedByBlueprint(FoundComponent FC, UBlueprint *BP);
|
||||
static bool CheckValidParent(FoundComponent FC, WingOut Errors);
|
||||
static bool CheckExists(FoundComponent FC, WingOut Errors);
|
||||
static bool CheckNoSuchComponent(FoundComponent FC, WingOut Errors);
|
||||
static bool CheckNotNative(FoundComponent FC, const TCHAR *Action, WingOut Errors);
|
||||
static bool CheckOwnedByBlueprint(FoundComponent FC, UBlueprint *BP, WingOut Errors);
|
||||
static void AddChildNode(UBlueprint *BP, USCS_Node *Node, FoundComponent Parent);
|
||||
static TMap<FName, FName> CalculateParentNames(USimpleConstructionScript *Script);
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "CoreMinimal.h"
|
||||
#include "Factories/Factory.h"
|
||||
#include "Factories/EnumFactory.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingFactories.generated.h"
|
||||
|
||||
|
||||
@@ -13,7 +14,7 @@ public:
|
||||
// Create an asset on disk, using a factory instance.
|
||||
// Returns the main object. If there are problems,
|
||||
// prints error messages and returns nullptr.
|
||||
static UObject *CreateAsset(const FString &Path, UFactory *Factory);
|
||||
static UObject *CreateAsset(const FString &Path, UFactory *Factory, WingOut Errors);
|
||||
|
||||
// Some factories are blacklisted, mainly because they
|
||||
// pop up dialog boxes. In those cases, we deal with it
|
||||
@@ -28,7 +29,7 @@ public:
|
||||
|
||||
// Verifies that the asset path is a valid path, and also
|
||||
// that there's not something already there at that path.
|
||||
static bool CheckNewAssetPath(const FString &Path);
|
||||
static bool CheckNewAssetPath(const FString &Path, WingOut Errors);
|
||||
};
|
||||
|
||||
// The original UEnumFactory may pop a dialog. We made a better one.
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
// output to WingServer::Printf.
|
||||
//
|
||||
bool Ok() const { return !bError; }
|
||||
|
||||
|
||||
// Try to fetch the current object as a UObject of
|
||||
// the specified type. If it isn't one, generates an
|
||||
// error and returns nullptr.
|
||||
@@ -75,19 +75,19 @@ public:
|
||||
|
||||
// Get the current object as a UObject if it is one,
|
||||
// otherwise nullptr. Does not generate errors.
|
||||
//
|
||||
//
|
||||
UObject* GetObj() const { return Obj; }
|
||||
|
||||
// Get the asset from where it all began: the first
|
||||
// step in the walk path. If the asset couldn't be
|
||||
// loaded, returns nullptr. Does not generate errors.
|
||||
//
|
||||
//
|
||||
UObject* GetAsset() const { return OriginalAsset; }
|
||||
|
||||
// Get the asset from where it all began: the first
|
||||
// step in the walk path, as a specified type. Errors
|
||||
// if it cannot cast to the specified type.
|
||||
//
|
||||
//
|
||||
template<class T> T* CastAsset()
|
||||
{
|
||||
if (!CheckAssetIsA(T::StaticClass())) return nullptr;
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
// opened. Get the editor. You must specify the type
|
||||
// that you expect the asset to be, and the type to cast
|
||||
// the editor to. Does not generate errors.
|
||||
//
|
||||
//
|
||||
template<class AssetType, class EditorType>
|
||||
EditorType* CastEditor()
|
||||
{
|
||||
@@ -115,16 +115,16 @@ public:
|
||||
// Initialize empty. You need to call Asset, or walk
|
||||
// a path that starts with an asset.
|
||||
//
|
||||
WingFetcher() {}
|
||||
WingFetcher(WingOut InErrors) : Errors(InErrors) {}
|
||||
|
||||
// Initialize with an object. From there, you can walk
|
||||
// to sub-objects.
|
||||
//
|
||||
WingFetcher(UObject* O) : Obj(O) {}
|
||||
WingFetcher(UObject* O, WingOut InErrors) : Obj(O), Errors(InErrors) {}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
// The Current Object. Only one of these can be non-null.
|
||||
UObject* Obj = nullptr;
|
||||
UEdGraphPin* ResultPin = nullptr;
|
||||
@@ -137,6 +137,9 @@ private:
|
||||
bool bError = false;
|
||||
bool bSkipNotify = false;
|
||||
|
||||
// Error reporting destination.
|
||||
WingOut Errors;
|
||||
|
||||
// Internal methods.
|
||||
using WalkFunc = WingFetcher& (WingFetcher::*)(const FString&);
|
||||
void SetObj(UObject* InObj);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
// Marker struct for handler parameters that accept a JSON object.
|
||||
// PopulateFromJson stashes the actual JSON object into the Json field.
|
||||
//
|
||||
USTRUCT()
|
||||
struct FWingJsonObject
|
||||
{
|
||||
@@ -17,6 +18,7 @@ struct FWingJsonObject
|
||||
|
||||
// Marker struct for handler parameters that accept a JSON array.
|
||||
// PopulateFromJson stashes the actual JSON array into the Array field.
|
||||
//
|
||||
USTRUCT()
|
||||
struct FWingJsonArray
|
||||
{
|
||||
@@ -56,4 +58,48 @@ public:
|
||||
|
||||
// The configuration object.
|
||||
UObject *ConfigurationObject;
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
// A 'WingOut' is our version of an output stream. It always
|
||||
// contains a pointer to a string builder, or nullptr.
|
||||
//
|
||||
class WingOut
|
||||
{
|
||||
public:
|
||||
WingOut(FStringBuilderBase *O) : Buffer(O) {}
|
||||
WingOut(FStringBuilderBase &O) : Buffer(&O) {}
|
||||
static WingOut Stdout;
|
||||
static WingOut None;
|
||||
|
||||
void PrintChar(TCHAR Ch) { if (Buffer) Buffer->AppendChar(Ch); }
|
||||
void Print(const TCHAR* Text) { if (Buffer) Buffer->Append(Text); }
|
||||
void Print(const FString& Text) { if (Buffer) Buffer->Append(Text); }
|
||||
template <typename FmtType, typename... ArgTypes>
|
||||
void Printf(const FmtType& Fmt, ArgTypes&&... Args)
|
||||
{ if (Buffer) Buffer->Appendf(Fmt, Forward<ArgTypes>(Args)...); }
|
||||
|
||||
static TStringBuilder<65536> StdoutBuffer;
|
||||
|
||||
private:
|
||||
FStringBuilderBase *Buffer;
|
||||
};
|
||||
|
||||
// A FWingStructAndUStruct is a pointer to a struct and its associated ustruct.
|
||||
//
|
||||
struct FWingStructAndUStruct
|
||||
{
|
||||
void *StructPtr;
|
||||
UStruct *UStructPtr;
|
||||
|
||||
// Copy constructor.
|
||||
FWingStructAndUStruct(FWingStructAndUStruct &Src) : StructPtr(Src.StructPtr), UStructPtr(Src.UStructPtr) {}
|
||||
|
||||
// Construct from a UObject.
|
||||
FWingStructAndUStruct(UObject *Obj) : StructPtr(Obj), UStructPtr(Obj->GetClass()) {}
|
||||
|
||||
// Construct from a UStruct pointer.
|
||||
template<class T, typename = std::enable_if_t<!std::is_base_of_v<UObject, T>>>
|
||||
FWingStructAndUStruct(T *Struct) : StructPtr(Struct), UStructPtr(Struct->StaticStruct()) {}
|
||||
};
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Materials/Material.h"
|
||||
#include "WingHandler.h"
|
||||
|
||||
class WingMaterialParameter
|
||||
{
|
||||
public:
|
||||
static TMap<FMaterialParameterInfo, FMaterialParameterMetadata> GetMaterialParameters(UMaterialInterface* Material);
|
||||
static bool ParseMaterialParameterAssociation(const FString& Str, EMaterialParameterAssociation& OutAssociation);
|
||||
static bool ParseMaterialParameterAssociation(const FString& Str, EMaterialParameterAssociation& OutAssociation, WingOut Errors);
|
||||
static void FormatMaterialParameter(const FMaterialParameterInfo& Info, const FMaterialParameterMetadata& Meta);
|
||||
};
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "CoreMinimal.h"
|
||||
#include "IPropertyRowGenerator.h"
|
||||
#include "PropertyHandle.h"
|
||||
#include "WingHandler.h"
|
||||
|
||||
class FJsonObject;
|
||||
class FJsonValue;
|
||||
@@ -44,35 +45,35 @@ public:
|
||||
TSharedPtr<IPropertyHandle> TryNamedProperty(const UStruct* ScriptStruct, uint8* Data, FName Name, bool RootFilter);
|
||||
|
||||
// Like TryNamedProperty, but prints an error if the property is not found.
|
||||
TSharedPtr<IPropertyHandle> NamedProperty(UObject* Obj, FName Name, bool RootFilter);
|
||||
TSharedPtr<IPropertyHandle> NamedProperty(const UStruct* ScriptStruct, uint8* Data, FName Name, bool RootFilter);
|
||||
TSharedPtr<IPropertyHandle> NamedProperty(UObject* Obj, FName Name, bool RootFilter, WingOut Errors);
|
||||
TSharedPtr<IPropertyHandle> NamedProperty(const UStruct* ScriptStruct, uint8* Data, FName Name, bool RootFilter, WingOut Errors);
|
||||
|
||||
// Get "details panel" properties for an object. Handles special
|
||||
// cases: blueprints (redirects to CDO), component references
|
||||
// (redirects to template), material graph nodes (includes
|
||||
// expression properties), widgets (includes slot properties).
|
||||
Handles GetDetails(UObject* Obj, bool Mutable);
|
||||
Handles GetDetails(UObject* Obj, bool Mutable, WingOut Errors);
|
||||
|
||||
// Organize properties by name. If there's more than one property
|
||||
// of a given name, print an error and returns false, and returns a map
|
||||
// that contains one of the two duplicates.
|
||||
static bool OrganizeByName(const Handles &H, TMap<FName, TSharedPtr<IPropertyHandle>> &Result);
|
||||
static bool OrganizeByName(const Handles &H, TMap<FName, TSharedPtr<IPropertyHandle>> &Result, WingOut Errors);
|
||||
|
||||
// Get/set text. Compared to the built in methods for getting and setting
|
||||
// text, these support more concise enum values, FEdGraphPinType, and
|
||||
// more concise Class properties.
|
||||
static FString GetText(IPropertyHandle& Handle);
|
||||
static bool SetText(IPropertyHandle& Handle, const FString& Text);
|
||||
static bool SetText(IPropertyHandle& Handle, const FString& Text, WingOut Errors);
|
||||
|
||||
// Store a Json value into a property handle. The Json value must be
|
||||
// a string, number, or boolean.
|
||||
static bool SetJson(IPropertyHandle& Handle, const TSharedPtr<FJsonValue>& JsonValue);
|
||||
static bool SetJson(IPropertyHandle& Handle, const TSharedPtr<FJsonValue>& JsonValue, WingOut Errors);
|
||||
|
||||
// Populate a whole bunch of properties from a Json object. If
|
||||
// AllOptional is true, the Json may supply a subset of the properties.
|
||||
// If not, the Json must supply all of them, excepting properties that
|
||||
// are explicitly marked Optional.
|
||||
static bool PopulateFromJson(TArray<TSharedPtr<IPropertyHandle>>& Props, const FJsonObject& Json, bool AllOptional);
|
||||
static bool PopulateFromJson(TArray<TSharedPtr<IPropertyHandle>>& Props, const FJsonObject& Json, bool AllOptional, WingOut Errors);
|
||||
|
||||
// Print a single property in a standardized format:
|
||||
// editable|readonly Type Name = Value
|
||||
|
||||
@@ -1,38 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingUtils.h"
|
||||
|
||||
// A resolved property: the FProperty descriptor plus a pointer to
|
||||
// the value's storage. operator-> forwards to the FProperty.
|
||||
// the value's storage.
|
||||
//
|
||||
struct FWingProperty
|
||||
{
|
||||
|
||||
FProperty* Prop = nullptr;
|
||||
void* Container = nullptr;
|
||||
|
||||
// Construct a property reference.
|
||||
//
|
||||
FWingProperty(FProperty* InProp, void* InContainer)
|
||||
: Prop(InProp), Container(InContainer) {}
|
||||
|
||||
// Construct a null property reference.
|
||||
//
|
||||
FWingProperty() = default;
|
||||
FWingProperty(FProperty* InProp, void* InContainer);
|
||||
FWingProperty(FProperty* InProp, UObject* InContainer);
|
||||
|
||||
bool SetDouble(double D);
|
||||
bool SetInt64(int64 I);
|
||||
bool SetBool(bool B);
|
||||
// Operator -> forwards to the FProperty.
|
||||
//
|
||||
FProperty* operator->() const { return Prop; }
|
||||
|
||||
// Store a value. On failure, return false, and print an
|
||||
// error. These will do automatic conversion of numeric
|
||||
// types to other numeric types, as long as the value
|
||||
// fits. They will also do text to any type, as long as
|
||||
// the value parses as a value of the desired type. If
|
||||
// you
|
||||
//
|
||||
bool SetObject(UObject *Obj, WingOut Errors) const;
|
||||
bool SetDouble(double D, WingOut Errors) const;
|
||||
bool SetInt64(int64 I, WingOut Errors) const;
|
||||
bool SetBool(bool B, WingOut Errors) const;
|
||||
bool SetText(FString Value, WingOut Errors) const;
|
||||
bool SetJson(const FJsonValue &Value, WingOut Errors) const;
|
||||
|
||||
// Fetch a value. If an error occurs such as a type
|
||||
// mismatch, returns an empty optional and prints an
|
||||
// error. These will do automatic conversion of numeric
|
||||
// types to other numeric types, as long as the value
|
||||
// fits. They will also do any type to text, which is
|
||||
// why the GetText version needs no error reporting.
|
||||
//
|
||||
TOptional<UObject*> GetObject(WingOut Errors) const;
|
||||
TOptional<double> GetDouble(WingOut Errors) const;
|
||||
TOptional<int64> GetInt64(WingOut Errors) const;
|
||||
TOptional<bool> GetBool(WingOut Errors) const;
|
||||
FString GetText() const;
|
||||
bool SetText(FString Value);
|
||||
|
||||
// Store data from a json object.
|
||||
bool SetJson(const TSharedPtr<FJsonValue> &Value);
|
||||
|
||||
// Get the Category metadata.
|
||||
FString GetCategory();
|
||||
|
||||
// Get the text, replace newlines with whitespace, and
|
||||
// truncate to the specified maximum length.
|
||||
// Get the text, replace newlines with whitespace, and truncate to the specified maximum length.
|
||||
//
|
||||
FString GetTruncatedText(int32 MaxLen) const;
|
||||
|
||||
// Get the Category metadata.
|
||||
//
|
||||
FString GetCategory() const;
|
||||
|
||||
// Return true if the property is not the null property reference.
|
||||
//
|
||||
explicit operator bool() const { return Prop != nullptr; }
|
||||
FProperty* operator->() const { return Prop; }
|
||||
|
||||
// Get the raw properties of the specified object or struct.
|
||||
//
|
||||
// This gets the properties that are literally present in the
|
||||
// specified object or struct. No special interpretation is done.
|
||||
//
|
||||
static TArray<FWingProperty> GetAll(FWingStructAndUStruct Obj, EPropertyFlags Flags);
|
||||
|
||||
// Get just the names of the properties of the specified struct/class.
|
||||
//
|
||||
static TArray<FName> GetNames(UStruct *US, EPropertyFlags Flags);
|
||||
|
||||
// Remove any properties with the specified name.
|
||||
//
|
||||
static void Remove(TArray<FWingProperty>& Props, FName Name);
|
||||
|
||||
// Move any properties with the specified name to the out array.
|
||||
//
|
||||
static void Move(TArray<FWingProperty> &Out, TArray<FWingProperty> &In, FName Name);
|
||||
|
||||
// Return the "Details Panel" properties for the specified object.
|
||||
//
|
||||
@@ -46,49 +96,19 @@ struct FWingProperty
|
||||
//
|
||||
// When editing an inherited ActorComponent, you're actually editing
|
||||
// properties that *override* the original properties of the ActorComponent.
|
||||
// The mutable version, 'GetDetailsMutable', tells this function to first
|
||||
// create the overrides, and then edit those.
|
||||
//
|
||||
// For a more direct "just give me the properties of this object,"
|
||||
// use the GetAll function.
|
||||
// The 'mutable' flag tells it whether to create overrides for these
|
||||
// properties.
|
||||
//
|
||||
static TArray<FWingProperty> GetDetailsMutable(UObject* Obj, EPropertyFlags Flags)
|
||||
{ return GetDetailsGeneral(Obj, Flags, true); }
|
||||
static TArray<FWingProperty> GetDetailsImmutable(UObject *Obj, EPropertyFlags Flags)
|
||||
{ return GetDetailsGeneral(Obj, Flags, false); }
|
||||
|
||||
// Get the raw properties of the specified object or struct.
|
||||
//
|
||||
// This gets the properties that are literally present in the
|
||||
// specified object or struct. No special interpretation is done.
|
||||
//
|
||||
static TArray<FWingProperty> GetAll(UObject* Object, EPropertyFlags Flags);
|
||||
static TArray<FWingProperty> GetAll(UStruct* StructType, void* Container, EPropertyFlags Flags);
|
||||
|
||||
// Get the names of the properties in the specified class.
|
||||
//
|
||||
static TArray<FName> GetNames(UStruct *StructType, EPropertyFlags Flags);
|
||||
|
||||
// Get the named properties.
|
||||
//
|
||||
static TArray<FWingProperty> GetNamed(UStruct* StructType, void* Container, const TArray<FName> &Names);
|
||||
|
||||
// Functions to find items by name in an array of properties.
|
||||
//
|
||||
static TArray<FWingProperty> FindAllSubstring(const TArray<FWingProperty>& Props, const FString& Substring);
|
||||
static void Remove(TArray<FWingProperty>& Props, const FString& Name);
|
||||
static void Move(TArray<FWingProperty> &Out, TArray<FWingProperty> &In, const FString &Name);
|
||||
static TArray<FWingProperty> GetDetails(UObject* Obj, EPropertyFlags Flags, bool Mutable);
|
||||
|
||||
// Functions to populate properties from a JSON object.
|
||||
//
|
||||
static bool PopulateFromJson(FWingProperty& Prop, const FJsonObject* Json, bool AllOptional = false);
|
||||
static bool PopulateFromJson(TArray<FWingProperty>& Props, const FJsonObject* Json, bool AllOptional = false);
|
||||
static bool PopulateFromJson(UStruct* StructType, void* Container, const FJsonObject* Object);
|
||||
static bool PopulateFromJson(UStruct* StructType, void* Container, const TSharedPtr<FJsonValue>& Object);
|
||||
static bool PopulateFromJson(TArray<FWingProperty>& Props, const FJsonValue& Json,
|
||||
bool AllOptional, WingOut Errors);
|
||||
|
||||
private:
|
||||
static TArray<FWingProperty> GetDetailsGeneral(UObject* Obj, EPropertyFlags Flags, bool Mutable);
|
||||
void PrintExpectsReceived(const TCHAR *Type);
|
||||
static void Collect(UStruct* Struct, void* Container, TArray<FWingProperty> &Props, EPropertyFlags Flags);
|
||||
bool CheckImportTextResult(const FString &Value);
|
||||
static void GetAll(FWingStructAndUStruct Obj, EPropertyFlags Flags, TArray<FWingProperty> &Props);
|
||||
static bool IsPinTypeProperty(FProperty *Prop);
|
||||
void PrintExpectsReceived(const TCHAR *Type, WingOut Errors) const;
|
||||
bool CheckImportTextResult(const FString &Value, WingOut Errors) const;
|
||||
};
|
||||
|
||||
@@ -50,20 +50,6 @@ public:
|
||||
/** Track an object that has been modified by the current handler. */
|
||||
static void AddTouchedObject(UObject* Obj) { GWingServer->Notifier.AddTouchedObject(Obj); }
|
||||
|
||||
/** Print text to the handler output buffer. */
|
||||
static void Print(const TCHAR* Text) { GWingServer->HandlerOutput.Append(Text); }
|
||||
static void Print(const FString& Text) { GWingServer->HandlerOutput.Append(Text); }
|
||||
|
||||
/** Print formatted text to the handler output buffer. */
|
||||
template <typename FmtType, typename... ArgTypes>
|
||||
static void Printf(const FmtType& Fmt, ArgTypes&&... Args)
|
||||
{
|
||||
GWingServer->HandlerOutput.Appendf(Fmt, Forward<ArgTypes>(Args)...);
|
||||
}
|
||||
|
||||
/** Get the handler output buffer directly. */
|
||||
static FStringBuilderBase& GetPrintBuffer() { return GWingServer->HandlerOutput; }
|
||||
|
||||
/** Suggest that a manual section be printed after the handler finishes. */
|
||||
static void SuggestManual(WingManual::Section Section) { GWingServer->SuggestedManualSections.Add(Section); }
|
||||
|
||||
@@ -84,7 +70,6 @@ private:
|
||||
UPROPERTY()
|
||||
FWingNotifier Notifier;
|
||||
FWingHandlerConfig* LastHandler;
|
||||
TStringBuilder<16384> HandlerOutput;
|
||||
TSet<WingManual::Section> SuggestedManualSections;
|
||||
FLogCaptureOutputDevice LogCapture; // installed once at startup, enabled per-request
|
||||
TArray<FWingHandlerConfig> WingHandlerRegistry; // sorted by Name
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "CoreMinimal.h"
|
||||
#include "EditorSubsystem.h"
|
||||
#include "EdGraph/EdGraphPin.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingTypes.generated.h"
|
||||
|
||||
struct WingTokenizer;
|
||||
@@ -117,16 +118,16 @@ private:
|
||||
// Parser and ResolveShortName
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static void PrintParseError(WingTokenizer& Tok, const TCHAR* Message);
|
||||
static bool ParseChar(WingTokenizer& Tok, TCHAR c);
|
||||
bool ParsePlainIdentifier(WingTokenizer& Tok, FEdGraphPinType& OutType);
|
||||
bool ParseWrapped(WingTokenizer& Tok, FName Wrapper, FEdGraphPinType& OutType);
|
||||
bool ParseMaybeWrapped(WingTokenizer& Tok, FEdGraphPinType& OutType);
|
||||
bool ParseArrayOrSet(WingTokenizer& Tok, FEdGraphPinType& OutType);
|
||||
bool ParseMap(WingTokenizer& Tok, FEdGraphPinType& OutType);
|
||||
bool ParseType(WingTokenizer& Tok, FEdGraphPinType& OutType);
|
||||
static void PrintParseError(WingTokenizer& Tok, const TCHAR* Message, WingOut Errors);
|
||||
static bool ParseChar(WingTokenizer& Tok, TCHAR c, WingOut Errors);
|
||||
bool ParsePlainIdentifier(WingTokenizer& Tok, FEdGraphPinType& OutType, WingOut Errors);
|
||||
bool ParseWrapped(WingTokenizer& Tok, FName Wrapper, FEdGraphPinType& OutType, WingOut Errors);
|
||||
bool ParseMaybeWrapped(WingTokenizer& Tok, FEdGraphPinType& OutType, WingOut Errors);
|
||||
bool ParseArrayOrSet(WingTokenizer& Tok, FEdGraphPinType& OutType, WingOut Errors);
|
||||
bool ParseMap(WingTokenizer& Tok, FEdGraphPinType& OutType, WingOut Errors);
|
||||
bool ParseType(WingTokenizer& Tok, FEdGraphPinType& OutType, WingOut Errors);
|
||||
|
||||
bool ResolveShortName(WingTokenizer& Tok, const FString &Name, FEdGraphPinType &OutType);
|
||||
bool ResolveShortName(WingTokenizer& Tok, const FString &Name, FEdGraphPinType &OutType, WingOut Errors);
|
||||
|
||||
public:
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -146,21 +147,21 @@ public:
|
||||
// Parse a type. If it doesn't parse, or if the type doesn't satisfy the
|
||||
// requirements, prints an error and returns false. If CheckEOF is true,
|
||||
// makes sure that the input is *just* a type and nothing else after it.
|
||||
static bool TextToType(WingTokenizer &Tok, FEdGraphPinType& OutPinType, const Requirements &Require, bool CheckEOF);
|
||||
static bool TextToType(WingTokenizer &Tok, FEdGraphPinType& OutPinType, const Requirements &Require, bool CheckEOF, WingOut Errors);
|
||||
|
||||
// Parse a type. If it doesn't parse, or if the type doesn't satisfy the
|
||||
// requirements, prints an error and returns false.
|
||||
static bool TextToType(const FString& Text, FEdGraphPinType& OutPinType, const Requirements &Require);
|
||||
// requirements, prints an error and returns false.
|
||||
static bool TextToType(const FString& Text, FEdGraphPinType& OutPinType, const Requirements &Require, WingOut Errors);
|
||||
|
||||
// Parse a type. If it doesn't parse, or if the type doesn't satisfy the
|
||||
// requirements, prints an error and returns false. Requires that the type
|
||||
// is an object type (even if that's not specified in the requirements struct).
|
||||
static UClass* TextToOneObjectType(const FString& Text, const Requirements &Require);
|
||||
static UClass* TextToOneObjectType(const FString& Text, const Requirements &Require, WingOut Errors);
|
||||
|
||||
// Parse a type. If it doesn't parse, or if the type doesn't satisfy the
|
||||
// requirements, prints an error and returns false. Requires that the type
|
||||
// is an interface type (even if that's not specified in the requirements struct).
|
||||
static UClass* TextToOneInterfaceType(const FString& Text, const Requirements &Require);
|
||||
static UClass* TextToOneInterfaceType(const FString& Text, const Requirements &Require, WingOut Errors);
|
||||
|
||||
private:
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "Components/Widget.h"
|
||||
#include "WingActorComponent.h"
|
||||
#include "WingVariables.h"
|
||||
#include "WingHandler.h"
|
||||
|
||||
struct FEdGraphSchemaAction;
|
||||
class UAnimationStateMachineGraph;
|
||||
@@ -104,53 +105,53 @@ public:
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ArrayType>
|
||||
static auto FindOneWithInternalID(FName InternalID, ArrayType &&Array, const TCHAR *Kind)
|
||||
static auto FindOneWithInternalID(FName InternalID, ArrayType &&Array, const TCHAR *Kind, WingOut Errors)
|
||||
{
|
||||
decltype(EltAsPtr(Array, Array[0])) Result = nullptr;
|
||||
int Count = 0;
|
||||
for (auto &Elt : Array) if (GetFName(Elt) == InternalID) { Count++; Result = EltAsPtr(Array, Elt); }
|
||||
if (!CheckExactlyOneNamed(Count, Kind, InternalID)) Result = nullptr;
|
||||
if (!CheckExactlyOneNamed(Count, Kind, InternalID, Errors)) Result = nullptr;
|
||||
return Result;
|
||||
}
|
||||
|
||||
template<typename ArrayType>
|
||||
static auto FindOneWithExternalID(const FString &ExternalID, ArrayType &&Array, const TCHAR *Kind)
|
||||
static auto FindOneWithExternalID(const FString &ExternalID, ArrayType &&Array, const TCHAR *Kind, WingOut Errors)
|
||||
{
|
||||
decltype(EltAsPtr(Array, Array[0])) Result = nullptr;
|
||||
FName InternalID = CheckInternalizeID(ExternalID);
|
||||
if (!InternalID.IsNone()) Result = FindOneWithInternalID(InternalID, Array, Kind);
|
||||
FName InternalID = CheckInternalizeID(ExternalID, Errors);
|
||||
if (!InternalID.IsNone()) Result = FindOneWithInternalID(InternalID, Array, Kind, Errors);
|
||||
return Result;
|
||||
}
|
||||
|
||||
template<typename ArrayType>
|
||||
static bool FindNoneWithInternalID(FName InternalID, ArrayType &&Array, const TCHAR *Kind)
|
||||
static bool FindNoneWithInternalID(FName InternalID, ArrayType &&Array, const TCHAR *Kind, WingOut Errors)
|
||||
{
|
||||
for (auto &Elt : Array) if (GetFName(Elt) == InternalID)
|
||||
return CheckExactlyNoneNamed(1, Kind, InternalID);
|
||||
for (auto &Elt : Array) if (GetFName(Elt) == InternalID)
|
||||
return CheckExactlyNoneNamed(1, Kind, InternalID, Errors);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename ArrayType>
|
||||
static bool FindNoneWithExternalID(const FString &ExternalID, ArrayType &&Array, const TCHAR *Kind)
|
||||
static bool FindNoneWithExternalID(const FString &ExternalID, ArrayType &&Array, const TCHAR *Kind, WingOut Errors)
|
||||
{
|
||||
FName InternalID = CheckInternalizeID(ExternalID);
|
||||
FName InternalID = CheckInternalizeID(ExternalID, Errors);
|
||||
if (InternalID.IsNone()) return false;
|
||||
return FindNoneWithInternalID(InternalID, Array, Kind);
|
||||
return FindNoneWithInternalID(InternalID, Array, Kind, Errors);
|
||||
}
|
||||
|
||||
static bool FindNoDuplicateName(TSet<FName> &Collection, FName InternalID, const TCHAR *Kind)
|
||||
static bool FindNoDuplicateName(TSet<FName> &Collection, FName InternalID, const TCHAR *Kind, WingOut Errors)
|
||||
{
|
||||
if (Collection.Contains(InternalID))
|
||||
{ CheckExactlyOneNamed(2, Kind, InternalID); return false; }
|
||||
{ CheckExactlyOneNamed(2, Kind, InternalID, Errors); return false; }
|
||||
Collection.Add(InternalID);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename ArrayType>
|
||||
static bool FindNoDuplicateNames(TSet<FName> &Collection, ArrayType &&Array, const TCHAR *Kind)
|
||||
static bool FindNoDuplicateNames(TSet<FName> &Collection, ArrayType &&Array, const TCHAR *Kind, WingOut Errors)
|
||||
{
|
||||
for (auto &Elt : Array)
|
||||
if (!FindNoDuplicateName(Collection, GetFName(Elt), Kind)) return false;
|
||||
if (!FindNoDuplicateName(Collection, GetFName(Elt), Kind, Errors)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -200,7 +201,7 @@ public:
|
||||
// static FString ExternalizeID(const FString& InternalID);
|
||||
static FString ExternalizeID(FName Name);
|
||||
|
||||
static FName CheckInternalizeID(const FString &ExternalID);
|
||||
static FName CheckInternalizeID(const FString &ExternalID, WingOut Errors);
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// In Unreal, Menu items tend to be an unpredictable
|
||||
@@ -221,13 +222,13 @@ public:
|
||||
// empty string.
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
static FName CheckProposedName(const FString &Name);
|
||||
static FName CheckProposedName(const FString &Name, WingOut Errors);
|
||||
|
||||
static FString FormatNodeTitle(const UEdGraphNode *Node);
|
||||
|
||||
// ----- Enum helpers -----
|
||||
static FString EnumToString(UEnum* Enum, int64 Value);
|
||||
static bool StringToEnum(UEnum* Enum, const FString& Str, int64& OutValue);
|
||||
static bool StringToEnum(UEnum* Enum, const FString& Str, int64& OutValue, WingOut Errors);
|
||||
|
||||
template<typename T>
|
||||
static FString EnumToString(TEnumAsByte<T> Value)
|
||||
@@ -238,8 +239,8 @@ public:
|
||||
{ return EnumToString(StaticEnum<T>(), (int64)Value); }
|
||||
|
||||
template<typename T>
|
||||
static bool StringToEnum(const FString& Str, T& OutValue)
|
||||
{ int64 V; if (!StringToEnum(StaticEnum<T>(), Str, V)) return false; OutValue = (T)V; return true; }
|
||||
static bool StringToEnum(const FString& Str, T& OutValue, WingOut Errors)
|
||||
{ int64 V; if (!StringToEnum(StaticEnum<T>(), Str, V, Errors)) return false; OutValue = (T)V; return true; }
|
||||
|
||||
// ----- Blueprint helpers -----
|
||||
static TArray<UEdGraph*> AllGraphs(UBlueprint* BP);
|
||||
@@ -258,7 +259,7 @@ public:
|
||||
|
||||
// ----- Anim blueprint helpers -----
|
||||
static UAnimationStateMachineGraph* FindStateMachineGraph(UBlueprint* BP, const FString& GraphName);
|
||||
static UAnimStateNode* FindStateByName(UAnimationStateMachineGraph* SMGraph, const FString& StateName);
|
||||
static UAnimStateNode* FindStateByName(UAnimationStateMachineGraph* SMGraph, const FString& StateName, WingOut Errors);
|
||||
static UAnimStateTransitionNode* FindTransition(UAnimationStateMachineGraph* SMGraph, const FString& FromStateName, const FString& ToStateName);
|
||||
|
||||
// ----- Text formatting -----
|
||||
@@ -273,11 +274,11 @@ public:
|
||||
static bool CanReparentBlueprint(UClass* CurrentGenerated, UClass* Proposed);
|
||||
|
||||
// ----- Common Error Reporting -----
|
||||
static bool CheckExactlyOneNamed(int Count, const TCHAR *Kind, const FString &Name);
|
||||
static bool CheckExactlyOneNamed(int Count, const TCHAR *Kind, FName Name);
|
||||
static bool CheckExactlyNoneNamed(int Count, const TCHAR *Kind, const FString &Name);
|
||||
static bool CheckExactlyNoneNamed(int Count, const TCHAR *Kind, FName Name);
|
||||
static bool CheckExactlyOneNamed(int Count, const TCHAR *Kind, const FString &Name, WingOut Errors);
|
||||
static bool CheckExactlyOneNamed(int Count, const TCHAR *Kind, FName Name, WingOut Errors);
|
||||
static bool CheckExactlyNoneNamed(int Count, const TCHAR *Kind, const FString &Name, WingOut Errors);
|
||||
static bool CheckExactlyNoneNamed(int Count, const TCHAR *Kind, FName Name, WingOut Errors);
|
||||
|
||||
static bool CheckCanRename(UEdGraphNode* Node, const FString &Name);
|
||||
static bool CheckCanRename(UEdGraphNode* Node, const FString &Name, WingOut Errors);
|
||||
};
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "CoreMinimal.h"
|
||||
#include "EdGraph/EdGraphPin.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "WingHandler.h"
|
||||
|
||||
struct WingTokenizer;
|
||||
class UK2Node_CustomEvent;
|
||||
@@ -54,27 +55,27 @@ public:
|
||||
void Empty() { Variables.Empty(); }
|
||||
|
||||
// Print the variables to a string builder.
|
||||
void Print(FStringBuilderBase &Out);
|
||||
void Print(WingOut Out);
|
||||
|
||||
// Print compact: "type name,type name,..."
|
||||
void PrintCompact(FStringBuilderBase &Out);
|
||||
void PrintCompact(WingOut Out);
|
||||
|
||||
// Clear the BPVar and Pin fields.
|
||||
void ClearLinks();
|
||||
|
||||
// Check the sanity of the vars in the array. If allow
|
||||
// is false, then no variables are allowed in the array.
|
||||
bool CheckSanity(const TSet<FName> &GoodFlags, bool Allow);
|
||||
bool CheckSanity(const TSet<FName> &GoodFlags, bool Allow, WingOut Errors);
|
||||
|
||||
// Parse variables from a string.
|
||||
bool ParseString(const FString &Input);
|
||||
bool ParseString(const FString &Input, WingOut Errors);
|
||||
|
||||
// Parse variable names only from a string.
|
||||
bool ParseNamesString(const FString &Input);
|
||||
bool ParseNamesString(const FString &Input, WingOut Errors);
|
||||
|
||||
private:
|
||||
bool ParseOneVariable(WingTokenizer &Tok, Var &V);
|
||||
bool ParseVariableFlags(WingTokenizer &Tok, TSet<FName> &Out);
|
||||
bool ParseOneVariable(WingTokenizer &Tok, Var &V, WingOut Errors);
|
||||
bool ParseVariableFlags(WingTokenizer &Tok, TSet<FName> &Out, WingOut Errors);
|
||||
};
|
||||
|
||||
class WingVariables
|
||||
@@ -100,7 +101,7 @@ public:
|
||||
// Configure the backing store. On failure,
|
||||
// prints a message and returns false.
|
||||
|
||||
bool SetBackingStore(UObject *Obj);
|
||||
bool SetBackingStore(UObject *Obj, WingOut Errors);
|
||||
|
||||
// Clear the workspace. Doesn't affect the backing store.
|
||||
|
||||
@@ -112,29 +113,29 @@ public:
|
||||
|
||||
// Print the contents of the workspace.
|
||||
|
||||
void Print(FStringBuilderBase &Out);
|
||||
void Print(WingOut Out);
|
||||
|
||||
// Load: clear the workspace, then
|
||||
// copy everything from the backing store into the workspace.
|
||||
|
||||
void Load();
|
||||
void Load(WingOut Errors);
|
||||
|
||||
// Check: make sure the contents of the workspace makes sense
|
||||
// given the type of backing store.
|
||||
|
||||
bool Check();
|
||||
bool Check(WingOut Errors);
|
||||
|
||||
// Use the variables in the workspace to modify the backing store.
|
||||
|
||||
bool Modify();
|
||||
bool Modify(WingOut Errors);
|
||||
|
||||
// Create every variable in the workspace in the backing store.
|
||||
|
||||
bool Create();
|
||||
bool Create(WingOut Errors);
|
||||
|
||||
// Remove every variable mentioned in the workspace from the backing store.
|
||||
|
||||
bool Remove();
|
||||
bool Remove(WingOut Errors);
|
||||
|
||||
private:
|
||||
void LoadBlueprint();
|
||||
@@ -144,37 +145,38 @@ private:
|
||||
Var LoadLocalVariableDescription(FBPVariableDescription &Desc);
|
||||
void LoadEditablePinBase(UK2Node_EditablePinBase *Node, WingVariableList &List);
|
||||
|
||||
bool CheckBlueprint();
|
||||
bool CheckGraph();
|
||||
bool CheckBlueprint(WingOut Errors);
|
||||
bool CheckGraph(WingOut Errors);
|
||||
|
||||
bool ModifyBlueprint();
|
||||
bool LinkBlueprintVariables();
|
||||
bool ModifyBlueprint(WingOut Errors);
|
||||
bool LinkBlueprintVariables(WingOut Errors);
|
||||
void ModifyBlueprintVariableFlags(Var &Input);
|
||||
bool ModifyBlueprintDefaults();
|
||||
bool ModifyBlueprintDefaults(WingOut Errors);
|
||||
|
||||
bool ModifyGraph();
|
||||
bool ModifyGraph(WingOut Errors);
|
||||
|
||||
bool CreateBlueprint();
|
||||
bool CreateBlueprint(WingOut Errors);
|
||||
|
||||
bool CreateGraph();
|
||||
bool CreateGraph(WingOut Errors);
|
||||
|
||||
bool RemoveBlueprint();
|
||||
bool RemoveGraph();
|
||||
bool RemoveBlueprint(WingOut Errors);
|
||||
bool RemoveGraph(WingOut Errors);
|
||||
|
||||
void LoadCustomEvent();
|
||||
bool CheckCustomEvent();
|
||||
bool ModifyCustomEvent();
|
||||
bool CreateCustomEvent();
|
||||
bool RemoveCustomEvent();
|
||||
bool CheckCustomEvent(WingOut Errors);
|
||||
bool ModifyCustomEvent(WingOut Errors);
|
||||
bool CreateCustomEvent(WingOut Errors);
|
||||
bool RemoveCustomEvent(WingOut Errors);
|
||||
|
||||
bool GetGraphNodes(
|
||||
UK2Node_EditablePinBase *&InputNode,
|
||||
UK2Node_EditablePinBase *&OutputNode,
|
||||
UK2Node_FunctionEntry *&LocalNode);
|
||||
UK2Node_FunctionEntry *&LocalNode,
|
||||
WingOut Errors);
|
||||
|
||||
bool ModifyEditablePinBase(WingVariableList &List, UK2Node_EditablePinBase *Node);
|
||||
bool ModifyEditablePinBase(WingVariableList &List, UK2Node_EditablePinBase *Node, WingOut Errors);
|
||||
void AddUserPinInfo(const Var &V, EEdGraphPinDirection Dir, UK2Node_EditablePinBase *Node);
|
||||
|
||||
bool ErrorNoBackingStore();
|
||||
bool ErrorNoBackingStore(WingOut Errors);
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/Widget.h"
|
||||
#include "WingHandler.h"
|
||||
|
||||
class UWidgetTree;
|
||||
struct FAssetData;
|
||||
@@ -24,7 +25,7 @@ public:
|
||||
TArray<Type> Search(const FString& Query, int32 MaxResults, bool Exact);
|
||||
|
||||
// Check if a widget can accept children. Prints error if not.
|
||||
static bool CheckCanBeParent(UWidget* Widget);
|
||||
static bool CheckCanBeParent(UWidget* Widget, WingOut Errors);
|
||||
|
||||
// Print out a tree of widgets, just showing the names and types.
|
||||
static void PrintWidgetTree(UWidget* Widget, int32 Depth);
|
||||
|
||||
Reference in New Issue
Block a user