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