More refinement of Wing server

This commit is contained in:
2026-03-19 12:01:38 -04:00
parent a9258f3a86
commit 9812a4a413
15 changed files with 60 additions and 155 deletions

View File

@@ -8,20 +8,14 @@
FWingBlueprintVar::FWingBlueprintVar(UBlueprint* BP, const FString& VarName)
{
FName VarFName(*VarName);
int32 VarIndex = FBlueprintEditorUtils::FindNewVariableIndex(BP, VarFName);
if (VarIndex == INDEX_NONE)
{
UWingServer::Printf(TEXT("ERROR: Variable '%s' not found in %s\n"), *VarName, *WingUtils::FormatName(BP));
return;
}
Desc = &BP->NewVariables[VarIndex];
Desc = WingUtils::FindExactlyOneNamed(VarName, BP->NewVariables);
if (!Desc) return;
// Try to find the default value property on the CDO.
if (BP->GeneratedClass)
{
UObject* CDO = BP->GeneratedClass->GetDefaultObject();
FProperty* Prop = BP->GeneratedClass->FindPropertyByName(VarFName);
FProperty* Prop = BP->GeneratedClass->FindPropertyByName(Desc->VarName);
if (CDO && Prop)
DefaultValueProp = FWingProperty(Prop, CDO);
}

View File

@@ -1,4 +1,5 @@
#include "WingGraphExport.h"
#include "WingProperty.h"
#include "WingTypes.h"
#include "WingUtils.h"
#include "Engine/Blueprint.h"
@@ -263,19 +264,19 @@ void WingGraphExport::EmitNode(UEdGraphNode* Node)
}
}
void WingGraphExport::EmitMaterialProperty(UMaterialExpression* Expression, FProperty* Prop, FStringBuilderBase& Out)
void WingGraphExport::EmitMaterialProperty(const FWingProperty& WP, FStringBuilderBase& Out)
{
FString ValueStr = WingUtils::GetPropertyValueText(Expression, Prop);
FString ValueStr = WP.GetText();
ValueStr.ReplaceInline(TEXT("\r\n"), TEXT(" "));
ValueStr.ReplaceInline(TEXT("\n"), TEXT(" "));
if (ValueStr.Len() > 80)
ValueStr = ValueStr.Left(80) + TEXT("...");
bool bEditable = !Prop->HasAnyPropertyFlags(CPF_EditConst);
bool bEditable = !WP->HasAnyPropertyFlags(CPF_EditConst);
Out.Appendf(TEXT(" %s %s %s = %s\n"),
bEditable ? TEXT("mxeditable") : TEXT("mxreadonly"),
*UWingTypes::TypeToText(Prop),
*WingUtils::FormatName(Prop),
*UWingTypes::TypeToText(WP.Prop),
*WingUtils::FormatName(WP.Prop),
*ValueStr);
}
@@ -286,13 +287,13 @@ void WingGraphExport::EmitMaterialProperties(UEdGraphNode* Node, FStringBuilderB
UMaterialExpression* Expression = MatNode->MaterialExpression;
FString PrimaryCategory = Expression->GetClass()->GetName();
TArray<FProperty*> Props = WingUtils::SearchProperties(Expression, FString(), CPF_Edit, false);
TArray<FWingProperty> Props = FWingProperty::GetAll(Expression, CPF_Edit);
for (FProperty* Prop : Props)
for (const FWingProperty& WP : Props)
{
FString Category = Prop->HasMetaData(TEXT("Category")) ? Prop->GetMetaData(TEXT("Category")) : FString();
FString Category = WP->HasMetaData(TEXT("Category")) ? WP->GetMetaData(TEXT("Category")) : FString();
if ((Category == PrimaryCategory) == bPrimary)
EmitMaterialProperty(Expression, Prop, Out);
EmitMaterialProperty(WP, Out);
}
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include "CoreMinimal.h"
#include "Misc/OutputDeviceRedirector.h"
class FLogCaptureOutputDevice : public FOutputDevice
{

View File

@@ -1,4 +1,5 @@
#include "WingNotifier.h"
#include "Editor.h"
#include "EdGraph/EdGraphNode.h"
#include "EdGraph/EdGraph.h"
#include "Engine/Blueprint.h"

View File

@@ -319,7 +319,7 @@ void UWingServer::TryCallHandler(const FString &Line)
if (!WingJson::PopulateFromJson(HandlerObj->GetClass(), HandlerObj.Get(), &*Request))
{
UWingServer::Printf(TEXT("\nUsage:\n\n"));
WingUtils::FormatCommandHelp(*HandlerClass);
WingUtils::PrintHandlerHelp(*HandlerClass);
return;
}

View File

@@ -508,11 +508,7 @@ TArray<TSharedPtr<FEdGraphSchemaAction>> WingUtils::SearchGraphActions(UEdGraph*
}
// ============================================================
// PopulateFromJson — fill a USTRUCT from a JSON object
// ============================================================
// ============================================================
// CollectHandlerClasses — find all concrete IWingHandler classes
// Support for locating UE Wingman Handlers
// ============================================================
TArray<UClass*> WingUtils::CollectHandlerClasses()
@@ -529,26 +525,16 @@ TArray<UClass*> WingUtils::CollectHandlerClasses()
return Result;
}
// ============================================================
// GetHandlerName — derive tool name from handler class name
// ============================================================
FString WingUtils::GetHandlerName(UClass* HandlerClass)
{
FString Name = HandlerClass->GetName();
// Strip "Wing_" prefix
Name.RemoveFromStart(TEXT("Wing_"));
return Name;
}
// ============================================================
// GetHandlerGroup — derive group name from handler class name
// ============================================================
FString WingUtils::GetHandlerGroup(UClass* HandlerClass)
{
FString Name = HandlerClass->GetName();
// Strip "Wing_" prefix
Name.RemoveFromStart(TEXT("Wing_"));
// Everything before the underscore is the group
int32 UnderscoreIdx;
@@ -558,108 +544,10 @@ FString WingUtils::GetHandlerGroup(UClass* HandlerClass)
}
// ============================================================
// GetTemplate
// PrintHandlerHelp — verbose description of one handler command
// ============================================================
// ============================================================
// FindPropertyByName
// ============================================================
FProperty* WingUtils::FindPropertyByName(UObject* Obj, const FString& Name)
{
if (!Obj)
{
UWingServer::Print(TEXT("ERROR: Object is null\n"));
return nullptr;
}
FProperty* Found = nullptr;
for (TFieldIterator<FProperty> PropIt(Obj->GetClass()); PropIt; ++PropIt)
{
if (!Identifies(Name, *PropIt)) continue;
if (Found)
{
UWingServer::Printf(TEXT("ERROR: Ambiguous property '%s' on %s\n"), *Name, *FormatName(Obj->GetClass()));
return nullptr;
}
Found = *PropIt;
}
if (!Found)
UWingServer::Printf(TEXT("ERROR: Property '%s' not found on %s\n"), *Name, *FormatName(Obj->GetClass()));
return Found;
}
// ============================================================
// GetPropertyValueText
// ============================================================
FString WingUtils::GetPropertyValueText(UObject* Container, FProperty* Prop)
{
FString Result;
void* ValuePtr = Prop->ContainerPtrToValuePtr<void>(Container);
Prop->ExportTextItem_Direct(Result, ValuePtr, nullptr, Container, PPF_None);
return Result;
}
// ============================================================
// SetPropertyValueText
// ============================================================
bool WingUtils::SetPropertyValueText(UObject* Container, FProperty* Prop, const FString& Value)
{
void* ValuePtr = Prop->ContainerPtrToValuePtr<void>(Container);
const TCHAR* ImportResult = Prop->ImportText_Direct(*Value, ValuePtr, Container, PPF_None);
if (!ImportResult)
{
UWingServer::Printf(TEXT("ERROR: Failed to parse '%s' for property '%s' (type: %s)\n"),
*Value, *FormatName(Prop), *Prop->GetCPPType());
return false;
}
return true;
}
bool WingUtils::SetPropertyValueText(void* Container, FProperty* Prop, const FString& Value, UObject* Owner)
{
void* ValuePtr = Prop->ContainerPtrToValuePtr<void>(Container);
const TCHAR* ImportResult = Prop->ImportText_Direct(*Value, ValuePtr, Owner, PPF_None);
if (!ImportResult)
{
UWingServer::Printf(TEXT("ERROR: Failed to parse '%s' for property '%s' (type: %s)\n"),
*Value, *FormatName(Prop), *Prop->GetCPPType());
return false;
}
return true;
}
// ============================================================
// SearchProperties
// ============================================================
TArray<FProperty*> WingUtils::SearchProperties(UObject* Obj, const FString& Query, EPropertyFlags Flags, bool bLocal)
{
TArray<FProperty*> Result;
if (!Obj) return Result;
UClass* ObjClass = Obj->GetClass();
for (TFieldIterator<FProperty> PropIt(ObjClass); PropIt; ++PropIt)
{
FProperty* Prop = *PropIt;
if (!Prop) continue;
if (Flags != 0 && !Prop->HasAnyPropertyFlags(Flags)) continue;
if (bLocal && Prop->GetOwnerStruct() != ObjClass) continue;
if (!Query.IsEmpty() && !FormatName(Prop).Contains(Query, ESearchCase::IgnoreCase))
continue;
Result.Add(Prop);
}
return Result;
}
// ============================================================
// FormatCommandHelp — verbose description of one handler command
// ============================================================
void WingUtils::FormatCommandHelp(UClass* HandlerClass)
void WingUtils::PrintHandlerHelp(UClass* HandlerClass)
{
const IWingHandler* Handler = Cast<IWingHandler>(HandlerClass->GetDefaultObject());
if (!Handler) return;