From c006531bd41369c6016bc3e897c1b5becd8a0b19 Mon Sep 17 00:00:00 2001 From: jyelon Date: Sat, 4 Apr 2026 17:59:00 -0400 Subject: [PATCH] Create_OneArg now working --- Docs/Unsupported-SingleClass-Factories.md | 100 ++++++ .../Source/UEWingman/Handlers/Asset_Delete.h | 2 +- .../Source/UEWingman/Handlers/Asset_Search.h | 6 +- .../UEWingman/Handlers/BlueprintGraph_Add.h | 4 +- .../Handlers/BlueprintInterface_Remove.h | 2 +- .../UEWingman/Handlers/Create_Blueprint.h | 95 ------ .../UEWingman/Handlers/Create_ClassArg.h | 302 ++++++++++++++++++ ...{Create_UsingFactory.h => Create_NoArgs.h} | 10 +- .../Handlers/Documentation_Commands.h | 4 +- .../Handlers/Documentation_CreateAssets.h | 4 +- .../Handlers/GraphNode_SearchTypes.h | 2 +- .../UEWingman/Handlers/GraphPin_Disconnect.h | 2 +- .../Source/UEWingman/Handlers/Graph_Dump.h | 2 +- .../UEWingman/Handlers/SysInfo_Factories.h | 1 + .../UEWingman/Handlers/TypeName_Search.h | 4 +- .../Source/UEWingman/Handlers/Variables_Add.h | 8 +- .../UEWingman/Handlers/Variables_Modify.h | 8 +- .../UEWingman/Handlers/Variables_Remove.h | 8 +- .../Source/UEWingman/Handlers/Widget_Add.h | 4 +- .../UEWingman/Handlers/Widget_SearchTypes.h | 2 +- 20 files changed, 442 insertions(+), 128 deletions(-) create mode 100644 Docs/Unsupported-SingleClass-Factories.md delete mode 100644 Plugins/UEWingman/Source/UEWingman/Handlers/Create_Blueprint.h create mode 100644 Plugins/UEWingman/Source/UEWingman/Handlers/Create_ClassArg.h rename Plugins/UEWingman/Source/UEWingman/Handlers/{Create_UsingFactory.h => Create_NoArgs.h} (78%) diff --git a/Docs/Unsupported-SingleClass-Factories.md b/Docs/Unsupported-SingleClass-Factories.md new file mode 100644 index 00000000..b6edb574 --- /dev/null +++ b/Docs/Unsupported-SingleClass-Factories.md @@ -0,0 +1,100 @@ +# Unsupported Factories with 1 Class-Type Parameter + +## Standard candidates (class picker, flag-based filtering) + +All of these follow the same basic pattern: TSubclassOf, open a +class picker dialog, filter on class flags. + +- AudioSynesthesiaNRTFactory — AudioSynesthesiaNRTClass + TSubclassOf + Flags: no abstract, no deprecated, no newer-version-exists + +- AudioSynesthesiaNRTSettingsFactory — AudioSynesthesiaNRTSettingsClass + TSubclassOf + Flags: no abstract, no deprecated, no newer-version-exists + +- AudioSynesthesiaSettingsFactory — AudioSynesthesiaSettingsClass + TSubclassOf + Flags: no abstract, no deprecated, no newer-version-exists + +- CurveFactory — CurveClass + TSubclassOf + Flags: no abstract, no deprecated, no newer-version-exists + Also checks CanCreateAssetOfClass() + +- DataAssetFactory — DataAssetClass + TSubclassOf + Flags: no abstract, no deprecated, no newer-version-exists, no hide-dropdown + Also checks CanCreateAssetOfClass() + +- InputAction_Factory — InputActionClass + TSubclassOf + Flags: no abstract, no deprecated, no newer-version-exists, no hide-dropdown + Skips dialog if no subtypes exist + +- InputMappingContext_Factory — InputMappingContextClass + TSubclassOf + Flags: no abstract, no deprecated, no newer-version-exists, no hide-dropdown + Skips dialog if no subtypes exist + +- PhysicalMaterialFactoryNew — PhysicalMaterialClass + TSubclassOf + Flags: no abstract, no deprecated, no newer-version-exists + Also checks CanCreateAssetOfClass() + +- PhysicalMaterialMaskFactory — PhysicalMaterialMaskClass + TSubclassOf + Flags: no abstract, no deprecated, no newer-version-exists + Also checks CanCreateAssetOfClass() + +- SoundSourceEffectFactory — SoundEffectSourcepresetClass + TSubclassOf + Flags: no abstract, no deprecated, no newer-version-exists + +- SoundSubmixEffectFactory — SoundEffectSubmixPresetClass + TSubclassOf + Flags: no abstract, no deprecated, no newer-version-exists + +## Slightly unusual candidates + +- CameraAssetFactory — CameraDirectorClass + TSubclassOf + Flags: no abstract, no deprecated (does NOT check newer-version-exists) + Allows "None" option (parameter can be null) + +- SlateWidgetStyleAssetFactory — StyleType + TSubclassOf + Flags: no abstract, no deprecated, no newer-version-exists + Explicitly excludes the base class itself + +- TemplateSequenceFactoryNew — BoundActorClass + TSubclassOf but dialog restricts to actors only (bIsActorsOnly) + Effective base class is AActor + No explicit flag filtering beyond class viewer defaults + +## Complex / special cases (probably not suitable for Create_ClassArg) + +- ControlRigBlueprintFactory — ParentClass + TSubclassOf + Complex custom filter: native-only, must have IsBlueprintBase="true" + metadata, no blueprint parents. Also calls CanCreateBlueprintOfClass + in FactoryCreateNew. Dialog gated behind a CVar. + +- LiveLinkBlueprintVirtualSubjectFactory — ParentClass + ParentClass is hardcoded. The actual configured parameter is "Role" + (TSubclassOf) with a custom modal dialog and a filter + that checks IsAllowableBlueprintVariableType on the role's structs. + Different parameter than what SysInfo_Factories reported. + +## Not class parameters at all (remove from consideration) + +- MetaSoundFactory — ReferencedMetaSoundObject + TObjectPtr, not TSubclassOf. Optional reference to an + existing MetaSound object for preset initialization. + +- MetaSoundSourceFactory — ReferencedMetaSoundObject + Same as above. + +- ObjectMixerBlueprintFilterFactory — ParentClass + Hardcoded to UObjectMixerBlueprintObjectFilter in constructor. + No config dialog. Nothing to configure. diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Asset_Delete.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Asset_Delete.h index 885043f5..1e364298 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Asset_Delete.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Asset_Delete.h @@ -26,7 +26,7 @@ public: UPROPERTY(EditAnywhere, meta=(Description="Asset to delete")) FString Asset; - UPROPERTY(meta=(Optional, Description="If true, skip reference check and force delete")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="If true, skip reference check and force delete")) bool Force = false; virtual void Register() override diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Asset_Search.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Asset_Search.h index e27425c4..6dab076a 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Asset_Search.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Asset_Search.h @@ -21,13 +21,13 @@ class UWing_Asset_Search : public UWingHandler GENERATED_BODY() public: - UPROPERTY(meta=(Optional, Description="Substring to match against asset package paths")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Substring to match against asset package paths")) FString Query; - UPROPERTY(meta=(Optional, Description="Asset class name to filter by, e.g. Blueprint, Material, StaticMesh")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Asset class name to filter by, e.g. Blueprint, Material, StaticMesh")) FString Type; - UPROPERTY(meta=(Optional, Description="Maximum number of results (default 50)")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Maximum number of results (default 50)")) int32 Limit = 50; virtual void Register() override diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintGraph_Add.h b/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintGraph_Add.h index dbd8a53b..c6168c76 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintGraph_Add.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintGraph_Add.h @@ -32,10 +32,10 @@ public: UPROPERTY(EditAnywhere, meta=(Description="Type of graph: function or macro")) FString GraphType; - UPROPERTY(meta=(Optional, Description="Input variables, one per line")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Input variables, one per line")) FString InputVariables; - UPROPERTY(meta=(Optional, Description="Output variables, one per line")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Output variables, one per line")) FString OutputVariables; virtual void Register() override diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintInterface_Remove.h b/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintInterface_Remove.h index de0b5756..cc6b4b25 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintInterface_Remove.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/BlueprintInterface_Remove.h @@ -27,7 +27,7 @@ public: UPROPERTY(EditAnywhere, meta=(Description="Interface name to remove")) FString Interface; - UPROPERTY(meta=(Optional, Description="If true, keep the function graphs as regular functions")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="If true, keep the function graphs as regular functions")) bool PreserveFunctions = false; virtual void Register() override diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Create_Blueprint.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Create_Blueprint.h deleted file mode 100644 index 6c097e54..00000000 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Create_Blueprint.h +++ /dev/null @@ -1,95 +0,0 @@ -#pragma once - -#include "CoreMinimal.h" -#include "Factories/Factory.h" -#include "WingServer.h" -#include "WingHandler.h" -#include "WingFactories.h" -#include "WingProperty.h" -#include "WingTypes.h" -#include "Factories/BlueprintFactory.h" -#include "Factories/BlueprintMacroFactory.h" -#include "Factories/AnimBlueprintFactory.h" -#include "WidgetBlueprintFactory.h" -#include "EditorUtilityBlueprintFactory.h" -#include "EditorUtilityWidgetBlueprintFactory.h" -#include "Create_Blueprint.generated.h" - -UCLASS() -class UWing_Create_Blueprint : public UWingHandler -{ - GENERATED_BODY() - -public: - UPROPERTY(EditAnywhere, meta=(Description="Full asset path for the new asset (e.g. '/Game/MyFolder/MyAsset')")) - FString Path; - - UPROPERTY(meta=(Optional, Description="The parent class for the new blueprint")) - FString ParentClass; - - static UClass *BlueprintInterfaceFactoryStaticClass() - { - return FindObject(nullptr, TEXT("/Script/UnrealEd.BlueprintInterfaceFactory")); - } - - virtual void Register() override - { - UWingServer::AddHandler(this, TEXT("Create_Blueprint"), - UBlueprintFactory::StaticClass(), EWingHandlerKind::Create, - TEXT("Create a normal blueprint")); - UWingServer::AddHandler(this, TEXT("Create_BlueprintMacroLibrary"), - UBlueprintMacroFactory::StaticClass(), EWingHandlerKind::Create, - TEXT("Create a blueprint macro library")); - UWingServer::AddHandler(this, TEXT("Create_WidgetBlueprint"), - UWidgetBlueprintFactory::StaticClass(), EWingHandlerKind::Create, - TEXT("Create a widget blueprint")); - UWingServer::AddHandler(this, TEXT("Create_EditorUtilityBlueprint"), - UEditorUtilityBlueprintFactory::StaticClass(), EWingHandlerKind::Create, - TEXT("Create an editor utility blueprint")); - UWingServer::AddHandler(this, TEXT("Create_EditorUtilityWidgetBlueprint"), - UEditorUtilityWidgetBlueprintFactory::StaticClass(), EWingHandlerKind::Create, - TEXT("Create an editor utility widget blueprint")); - if (BlueprintInterfaceFactoryStaticClass() != nullptr) - UWingServer::AddHandler(this, TEXT("Create_BlueprintInterface"), - BlueprintInterfaceFactoryStaticClass(), EWingHandlerKind::Create, - TEXT("Create a blueprint interface")); - } - - virtual void Handle() override - { - if (!WingFactories::CheckNewAssetPath(Path, WingOut::Stdout)) return; - - // Resolve parent class, if specified. - UClass *ParentClassObj = nullptr; - if (!ParentClass.IsEmpty()) - { - UWingTypes::Requirements Req; - Req.BlueprintType = false; - Req.Blueprintable = true; - Req.AllowContainer = false; - ParentClassObj = UWingTypes::TextToOneObjectType(ParentClass, Req, WingOut::Stdout); - if (!ParentClassObj) return; - } - - // Make the factory. - UClass *FactoryClass = Cast(ConfigurationObject); - UFactory *Factory = NewObject(GetTransientPackage(), FactoryClass); - if (Factory == nullptr) - { - WingOut::Stdout.Printf(TEXT("ERROR: factory creation failed (bug)\n")); - return; - } - - // Set the 'ParentClass' property. - TArray Props = FWingProperty::GetAll(Factory, CPF_Edit); - FWingProperty *Prop = WingUtils::FindOneWithInternalID( - TEXT("ParentClass"), Props, TEXT("property"), WingOut::Stdout); - if (!Prop) return; - if (!Prop->SetObject(ParentClassObj, WingOut::Stdout)) return; - - // Create the asset using the factory. - UObject *Blueprint = WingFactories::CreateAsset(Path, Factory, WingOut::Stdout); - if (Blueprint == nullptr) return; - WingOut::Stdout.Printf(TEXT("Created.\n")); - } -}; diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Create_ClassArg.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Create_ClassArg.h new file mode 100644 index 00000000..1f6515fd --- /dev/null +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Create_ClassArg.h @@ -0,0 +1,302 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Factories/Factory.h" +#include "WingServer.h" +#include "WingHandler.h" +#include "WingTypes.h" +#include "WingProperty.h" +#include "WingFactories.h" +#include "Create_ClassArg.generated.h" + +struct FWingClassArgConfig +{ + const TCHAR *Factory; + const TCHAR *Base; + bool ValidPointer = true; // eg, not nullptr + bool ConcreteClass = false; // eg, not abstract class + bool LatestVersion = true; // eg, not deprecated and no newer version. + bool ShowInDropDown = true; // eg, not hide drop down + bool NativeClass = false; // eg, not generated class + bool TrueSubclass = false; // eg, not the base class itself + bool CanCreateAsset = false; // calls 'CanCreateAssetOfClass' + bool BlueprintBase = false; // + bool Blueprintable = false; // + bool CanCreateBlueprint = false; // +}; + +UCLASS() +class UWingClassArg : public UObject +{ + GENERATED_BODY() +public: + FWingClassArgConfig Config; + + UPROPERTY() + TSubclassOf FactoryClass; + + UPROPERTY() + TObjectPtr BaseClass; +}; + +UCLASS() +class UWing_Create_ClassArg : public UWingHandler +{ + GENERATED_BODY() + + UPROPERTY(editAnywhere) + FString Path; + + UPROPERTY(EditAnywhere) + FString Class; + +public: + void RegisterConfigs(TArrayView Configs) + { + // Build a map of factory name -> UClass for quick lookup. + TMap FactoryMap; + TArray FactoryClasses; + GetDerivedClasses(UFactory::StaticClass(), FactoryClasses); + for (UClass* C : FactoryClasses) FactoryMap.Add(C->GetName(), C); + + for (const FWingClassArgConfig& Cfg : Configs) + { + // Look up the factory class. + UClass** FoundFactory = FactoryMap.Find(Cfg.Factory); + if (!FoundFactory) + { + UE_LOG(LogTemp, Warning, TEXT("Create_ClassArg: factory '%s' not found, skipping"), Cfg.Factory); + continue; + } + + // Look up the base class. + UClass* BaseClass = FindObject(nullptr, Cfg.Base); + if (!BaseClass) + { + UE_LOG(LogTemp, Warning, TEXT("Create_ClassArg: base class '%s' not found, skipping"), Cfg.Base); + continue; + } + + // Create the config object. + UWingClassArg* Arg = NewObject(this); + Arg->Config = Cfg; + Arg->FactoryClass = *FoundFactory; + Arg->BaseClass = BaseClass; + + // Register the command. + FString FactoryName = WingFactories::DeriveFactoryName(*FoundFactory); + FString CommandName = FString::Printf(TEXT("Create_%s"), *FactoryName); + FString Doc = FString::Printf(TEXT("Create a new %s asset."), *FactoryName); + UWingServer::AddHandler(this, CommandName, Arg, EWingHandlerKind::Create, Doc); + } + } + + virtual void Register() override + { + RegisterConfigs({ + + // --- Standard candidates --- + + { .Factory = TEXT("AudioSynesthesiaNRTFactory"), + .Base = TEXT("/Script/AudioSynesthesia.AudioSynesthesiaNRT"), + .ConcreteClass = true }, + + { .Factory = TEXT("AudioSynesthesiaNRTSettingsFactory"), + .Base = TEXT("/Script/AudioSynesthesia.AudioSynesthesiaNRTSettings"), + .ConcreteClass = true }, + + { .Factory = TEXT("AudioSynesthesiaSettingsFactory"), + .Base = TEXT("/Script/AudioSynesthesia.AudioSynesthesiaSettings"), + .ConcreteClass = true }, + + { .Factory = TEXT("CurveFactory"), + .Base = TEXT("/Script/Engine.CurveBase"), + .ConcreteClass = true, .CanCreateAsset = true }, + + { .Factory = TEXT("DataAssetFactory"), + .Base = TEXT("/Script/Engine.DataAsset"), + .ConcreteClass = true, .CanCreateAsset = true }, + + { .Factory = TEXT("InputAction_Factory"), + .Base = TEXT("/Script/EnhancedInput.InputAction"), + .ConcreteClass = true }, + + { .Factory = TEXT("InputMappingContext_Factory"), + .Base = TEXT("/Script/EnhancedInput.InputMappingContext"), + .ConcreteClass = true }, + + { .Factory = TEXT("PhysicalMaterialFactoryNew"), + .Base = TEXT("/Script/PhysicsCore.PhysicalMaterial"), + .ConcreteClass = true, .CanCreateAsset = true }, + + { .Factory = TEXT("PhysicalMaterialMaskFactory"), + .Base = TEXT("/Script/Engine.PhysicalMaterialMask"), + .ConcreteClass = true, .CanCreateAsset = true }, + + { .Factory = TEXT("SoundSourceEffectFactory"), + .Base = TEXT("/Script/Engine.SoundEffectSourcePreset"), + .ConcreteClass = true }, + + { .Factory = TEXT("SoundSubmixEffectFactory"), + .Base = TEXT("/Script/Engine.SoundEffectSubmixPreset"), + .ConcreteClass = true }, + + // --- Slightly unusual --- + + { .Factory = TEXT("CameraAssetFactory"), + .Base = TEXT("/Script/GameplayCameras.CameraDirector"), + .ValidPointer = false, .ConcreteClass = true }, + + { .Factory = TEXT("SlateWidgetStyleAssetFactory"), + .Base = TEXT("/Script/SlateCore.SlateWidgetStyleContainerBase"), + .ConcreteClass = true, .TrueSubclass = true }, + + { .Factory = TEXT("TemplateSequenceFactoryNew"), + .Base = TEXT("/Script/Engine.Actor") }, + + // --- Blueprint factories --- + + { .Factory = TEXT("BlueprintFactory"), + .Base = TEXT("/Script/CoreUObject.Object"), + .Blueprintable = true, .CanCreateBlueprint = true }, + + { .Factory = TEXT("BlueprintMacroFactory"), + .Base = TEXT("/Script/CoreUObject.Object"), + .Blueprintable = true, .CanCreateBlueprint = true }, + + // BlueprintFunctionLibraryFactory is handled by Create_NoArgs. + + // BlueprintInterfaceFactory is handled by Create_NoArgs. + + { .Factory = TEXT("WidgetBlueprintFactory"), + .Base = TEXT("/Script/CoreUObject.Object"), + .Blueprintable = true, .CanCreateBlueprint = true }, + + { .Factory = TEXT("EditorUtilityBlueprintFactory"), + .Base = TEXT("/Script/CoreUObject.Object"), + .Blueprintable = true, .CanCreateBlueprint = true }, + + { .Factory = TEXT("EditorUtilityWidgetBlueprintFactory"), + .Base = TEXT("/Script/CoreUObject.Object"), + .Blueprintable = true, .CanCreateBlueprint = true }, + + { .Factory = TEXT("InterchangeBlueprintPipelineBaseFactory"), + .Base = TEXT("/Script/InterchangeCore.InterchangePipelineBase"), + .Blueprintable = true, .CanCreateBlueprint = true }, + + { .Factory = TEXT("InterchangeEditorBlueprintPipelineBaseFactory"), + .Base = TEXT("/Script/InterchangeEditorPipelines.InterchangeEditorPipelineBase"), + .Blueprintable = true, .CanCreateBlueprint = true }, + + { .Factory = TEXT("ControlRigBlueprintFactory"), + .Base = TEXT("/Script/ControlRig.ControlRig"), + .NativeClass = true, .BlueprintBase = true, .Blueprintable = true, .CanCreateBlueprint = true }, + }); + } + + virtual void Handle() override + { + // Get the configuration. + UWingClassArg *ConfObj = Cast(ConfigurationObject); + if (ConfObj == nullptr) + { + WingOut::Stdout.Print(TEXT("ERROR: Create_ClassArg config object not set properly (bug)\n")); + return; + } + FWingClassArgConfig &Config = ConfObj->Config; + + // Verify that the specified path is good. + if (!WingFactories::CheckNewAssetPath(Path, WingOut::Stdout)) return; + + // Parse the class string. + UClass *ClassObj = nullptr; + if (!Class.IsEmpty()) + { + UWingTypes::Requirements Req; + Req.BlueprintType = false; + Req.Blueprintable = Config.Blueprintable; + Req.AllowContainer = false; + Req.IsChildOf = ConfObj->BaseClass; + ClassObj = UWingTypes::TextToOneObjectType(Class, Req, WingOut::Stdout); + if (!ClassObj) return; + } + + // Check constraints. + if (Config.ValidPointer && (ClassObj == nullptr)) + { + WingOut::Stdout.Print(TEXT("ERROR: factory requires a non-empty class to be specified.")); + return; + } + if (ClassObj != nullptr) + { + if (Config.ConcreteClass && ClassObj->HasAnyClassFlags(CLASS_Abstract)) + { + WingOut::Stdout.Printf(TEXT("ERROR: class '%s' is abstract.\n"), *ClassObj->GetName()); + return; + } + if (Config.LatestVersion && ClassObj->HasAnyClassFlags(CLASS_Deprecated | CLASS_NewerVersionExists)) + { + WingOut::Stdout.Printf(TEXT("ERROR: class '%s' is deprecated or has a newer version.\n"), *ClassObj->GetName()); + return; + } + if (Config.ShowInDropDown && ClassObj->HasAnyClassFlags(CLASS_HideDropDown)) + { + WingOut::Stdout.Printf(TEXT("ERROR: class '%s' is hidden.\n"), *ClassObj->GetName()); + return; + } + if (Config.NativeClass && !ClassObj->HasAnyClassFlags(CLASS_Native)) + { + WingOut::Stdout.Printf(TEXT("ERROR: class '%s' is not a native class.\n"), *ClassObj->GetName()); + return; + } + if (Config.TrueSubclass && (ClassObj == ConfObj->BaseClass)) + { + WingOut::Stdout.Printf(TEXT("ERROR: class '%s' is the base class itself, a subclass is required.\n"), *ClassObj->GetName()); + return; + } + if (Config.CanCreateAsset && !ClassObj->CanCreateAssetOfClass()) + { + WingOut::Stdout.Printf(TEXT("ERROR: cannot create an asset of class '%s'.\n"), *ClassObj->GetName()); + return; + } + if (Config.BlueprintBase && !ClassObj->GetBoolMetaDataHierarchical(FBlueprintMetadata::MD_IsBlueprintBase)) + { + WingOut::Stdout.Printf(TEXT("ERROR: class '%s' is not marked as a blueprint base.\n"), *ClassObj->GetName()); + return; + } + if (Config.CanCreateBlueprint && !FKismetEditorUtilities::CanCreateBlueprintOfClass(ClassObj)) + { + WingOut::Stdout.Printf(TEXT("ERROR: cannot create a blueprint of class '%s'.\n"), *ClassObj->GetName()); + return; + } + } + + // Make the factory. + UFactory *Factory = NewObject(GetTransientPackage(), ConfObj->FactoryClass); + if (Factory == nullptr) + { + WingOut::Stdout.Printf(TEXT("ERROR: factory creation failed (bug)\n")); + return; + } + + // Set the 'Class' property. + TArray Props = FWingProperty::GetAll(Factory, CPF_Edit); + FWingProperty::Remove(Props, TEXT("BlueprintType")); + if (Props.Num() != 1) + { + WingOut::Stdout.Printf(TEXT("ERROR: Factory unexpectedly has multiple config properties (bug)\n")); + return; + } + if (!CastField(Props[0].Prop)) + { + WingOut::Stdout.Printf(TEXT("ERROR: Factory was expected to have a 'class' property (bug)\n")); + return; + } + if (!Props[0].SetObject(ClassObj, WingOut::Stdout)) return; + + // Create the asset using the factory. + UObject *Blueprint = WingFactories::CreateAsset(Path, Factory, WingOut::Stdout); + if (Blueprint == nullptr) return; + WingOut::Stdout.Printf(TEXT("Created.\n")); + } +}; diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Create_UsingFactory.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Create_NoArgs.h similarity index 78% rename from Plugins/UEWingman/Source/UEWingman/Handlers/Create_UsingFactory.h rename to Plugins/UEWingman/Source/UEWingman/Handlers/Create_NoArgs.h index d956bfa9..036bf0cb 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Create_UsingFactory.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Create_NoArgs.h @@ -6,10 +6,10 @@ #include "WingHandler.h" #include "WingFactories.h" #include "Factories/BlueprintFunctionLibraryFactory.h" -#include "Create_UsingFactory.generated.h" +#include "Create_NoArgs.generated.h" UCLASS() -class UWing_Create_UsingFactory : public UWingHandler +class UWing_Create_NoArgs : public UWingHandler { GENERATED_BODY() @@ -35,6 +35,12 @@ public: UWingServer::AddHandler(this, TEXT("Create_BlueprintFunctionLibrary"), UBlueprintFunctionLibraryFactory::StaticClass(), EWingHandlerKind::Create, TEXT("Create a blueprint function library")); + + UClass *BlueprintInterfaceFactory = FindObject(nullptr, TEXT("/Script/UnrealEd.BlueprintInterfaceFactory")); + if (BlueprintInterfaceFactory) + UWingServer::AddHandler(this, TEXT("Create_BlueprintInterface"), + BlueprintInterfaceFactory, EWingHandlerKind::Create, + TEXT("Create a blueprint interface")); } virtual void Handle() override diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Documentation_Commands.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Documentation_Commands.h index 63ad766c..236967c7 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Documentation_Commands.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Documentation_Commands.h @@ -15,10 +15,10 @@ class UWing_Documentation_Commands : public UWingHandler GENERATED_BODY() public: - UPROPERTY(meta=(Optional, Description="Substring filter for command names")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Substring filter for command names")) FString Query; - UPROPERTY(meta=(Optional, Description="If true, return full details including parameter types and descriptions")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="If true, return full details including parameter types and descriptions")) bool Verbose = false; virtual void Register() override diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Documentation_CreateAssets.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Documentation_CreateAssets.h index fef86c5b..77171295 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Documentation_CreateAssets.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Documentation_CreateAssets.h @@ -15,10 +15,10 @@ class UWing_Documentation_CreateAssets : public UWingHandler GENERATED_BODY() public: - UPROPERTY(meta=(Optional, Description="Substring filter for command names")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Substring filter for command names")) FString Query; - UPROPERTY(meta=(Optional, Description="If true, return full details including parameter types and descriptions")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="If true, return full details including parameter types and descriptions")) bool Verbose = false; virtual void Register() override diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_SearchTypes.h b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_SearchTypes.h index b499a7cb..ef66bc9f 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_SearchTypes.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphNode_SearchTypes.h @@ -24,7 +24,7 @@ public: UPROPERTY(EditAnywhere, meta=(Description="Query string, can contain *")) FString Query; - UPROPERTY(meta=(Optional, Description="Maximum number of results (default 50)")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Maximum number of results (default 50)")) int32 MaxResults = 50; UPROPERTY(EditAnywhere, meta=(Description="Target graph")) diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphPin_Disconnect.h b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphPin_Disconnect.h index d9becbfa..97891876 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/GraphPin_Disconnect.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/GraphPin_Disconnect.h @@ -24,7 +24,7 @@ struct FDisconnectPinEntry UPROPERTY() FString Pin; - UPROPERTY(meta=(Optional)) + UPROPERTY(EditAnywhere, meta=(Optional)) FString TargetPin; }; diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Graph_Dump.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Graph_Dump.h index 30f93949..81f475cc 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Graph_Dump.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Graph_Dump.h @@ -26,7 +26,7 @@ public: UPROPERTY(EditAnywhere, meta=(Description="Path to graph")) FString Graph; - UPROPERTY(meta=(Optional, Description="True to include less-significant details")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="True to include less-significant details")) bool IncludeDetails; virtual void Register() override diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/SysInfo_Factories.h b/Plugins/UEWingman/Source/UEWingman/Handlers/SysInfo_Factories.h index 36c8a03e..9b6bd449 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/SysInfo_Factories.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/SysInfo_Factories.h @@ -4,6 +4,7 @@ #include "WingServer.h" #include "WingHandler.h" #include "WingFactories.h" +#include "Create_ClassArg.h" #include "SysInfo_Factories.generated.h" diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/TypeName_Search.h b/Plugins/UEWingman/Source/UEWingman/Handlers/TypeName_Search.h index 5d9b4c22..c3881e02 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/TypeName_Search.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/TypeName_Search.h @@ -26,10 +26,10 @@ public: UPROPERTY(EditAnywhere, meta=(Description="Substring filter for type names")) FString Query; - UPROPERTY(meta=(Optional, Description="Maximum number of results")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Maximum number of results")) int32 Limit = 100; - UPROPERTY(meta=(Optional, Description="If true, include all types, not just BlueprintType/Blueprintable ones")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="If true, include all types, not just BlueprintType/Blueprintable ones")) bool Exhaustive = false; virtual void Register() override diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Variables_Add.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Variables_Add.h index eccd9228..3c4cb280 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Variables_Add.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Variables_Add.h @@ -21,16 +21,16 @@ public: UPROPERTY(EditAnywhere, meta=(Description="Path to a blueprint, graph, or custom event node")) FString Object; - UPROPERTY(meta=(Optional, Description="Blueprint variables, one per line")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Blueprint variables, one per line")) FString BlueprintVariables; - UPROPERTY(meta=(Optional, Description="Input variables, one per line")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Input variables, one per line")) FString InputVariables; - UPROPERTY(meta=(Optional, Description="Output variables, one per line")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Output variables, one per line")) FString OutputVariables; - UPROPERTY(meta=(Optional, Description="Local variables, one per line")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Local variables, one per line")) FString LocalVariables; virtual void Register() override diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Variables_Modify.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Variables_Modify.h index 28256169..58bc2698 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Variables_Modify.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Variables_Modify.h @@ -21,16 +21,16 @@ public: UPROPERTY(EditAnywhere, meta=(Description="Path to a blueprint, graph, or custom event node")) FString Object; - UPROPERTY(meta=(Optional, Description="Blueprint variables, one per line")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Blueprint variables, one per line")) FString BlueprintVariables; - UPROPERTY(meta=(Optional, Description="Input variables, one per line")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Input variables, one per line")) FString InputVariables; - UPROPERTY(meta=(Optional, Description="Output variables, one per line")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Output variables, one per line")) FString OutputVariables; - UPROPERTY(meta=(Optional, Description="Local variables, one per line")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Local variables, one per line")) FString LocalVariables; virtual void Register() override diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Variables_Remove.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Variables_Remove.h index a5249642..4c626a9c 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Variables_Remove.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Variables_Remove.h @@ -21,16 +21,16 @@ public: UPROPERTY(EditAnywhere, meta=(Description="Path to a blueprint, graph, or custom event node")) FString Object; - UPROPERTY(meta=(Optional, Description="Blueprint variable names to remove, comma-separated")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Blueprint variable names to remove, comma-separated")) FString BlueprintVariables; - UPROPERTY(meta=(Optional, Description="Input variable names to remove, comma-separated")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Input variable names to remove, comma-separated")) FString InputVariables; - UPROPERTY(meta=(Optional, Description="Output variable names to remove, comma-separated")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Output variable names to remove, comma-separated")) FString OutputVariables; - UPROPERTY(meta=(Optional, Description="Local variable names to remove, comma-separated")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Local variable names to remove, comma-separated")) FString LocalVariables; virtual void Register() override diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Widget_Add.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Widget_Add.h index 2db17329..f313d96e 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Widget_Add.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Widget_Add.h @@ -33,10 +33,10 @@ public: UPROPERTY(EditAnywhere, meta=(Description="Name for the new widget")) FString Name; - UPROPERTY(meta=(Optional, Description="Parent widget name. If omitted, sets as root.")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Parent widget name. If omitted, sets as root.")) FString Parent; - UPROPERTY(meta=(Optional, Description="Whether to expose the widget as a variable in the blueprint (default false)")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Whether to expose the widget as a variable in the blueprint (default false)")) bool IsVariable = false; virtual void Register() override diff --git a/Plugins/UEWingman/Source/UEWingman/Handlers/Widget_SearchTypes.h b/Plugins/UEWingman/Source/UEWingman/Handlers/Widget_SearchTypes.h index df038518..692b2366 100644 --- a/Plugins/UEWingman/Source/UEWingman/Handlers/Widget_SearchTypes.h +++ b/Plugins/UEWingman/Source/UEWingman/Handlers/Widget_SearchTypes.h @@ -20,7 +20,7 @@ public: UPROPERTY(EditAnywhere, meta=(Description="Query string, can contain *")) FString Query; - UPROPERTY(meta=(Optional, Description="Maximum number of results (default 50)")) + UPROPERTY(EditAnywhere, meta=(Optional, Description="Maximum number of results (default 50)")) int32 MaxResults = 50; virtual void Register() override