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