属性窗口的的每个Item都是由FDetailPropertyRow造的。
不同的Value对应不同的Slate控件由SPropertyValueWidget生成。
一直看源码,现在为解决的就是valueToSlate,这个一开始想自己写后面想想UE4应该有的,于是就找到了,纪录一下:
TSharedRef<FPropertyNode> PropertyNodeRef = PropertyNode.ToSharedRef(); PropertyHandle = InParentCategory->GetParentLayoutImpl().GetPropertyHandle(PropertyNodeRef); const TSharedRef<IPropertyUtilities> Utilities = InParentCategory->GetParentLayoutImpl().GetPropertyUtilities(); if (PropertyNode->AsCategoryNode() == nullptr) { MakePropertyEditor(PropertyNodeRef, Utilities, PropertyEditor); }重点是怎么构造PropertyEditor和PropertyNode,因为后面要用到。
再看MakePropertyEditor
TSharedRef<FPropertyEditor> FDetailPropertyRow::MakePropertyEditor(const TSharedRef<FPropertyNode>& InPropertyNode, const TSharedRef<IPropertyUtilities>& PropertyUtilities, TSharedPtr<FPropertyEditor>& InEditor ) { if( !InEditor.IsValid() ) { InEditor = FPropertyEditor::Create( InPropertyNode, PropertyUtilities ); } return InEditor.ToSharedRef(); }以上类均是模块私有类,因为没导出,外部模块根本用不了(链接找不到符号),于是就想到了接口类,于是就直接这样用就行咯。
void FMyClassCustomization::CustomizeDetails(IDetailLayoutBuilder & DetailBuilder) { const FName DefaultCategoryName = NAME_None; IDetailCategoryBuilder& DefaultCategory = DetailBuilder.EditCategory(DefaultCategoryName); DetailBuilder.HideCategory("TestObject"); TArray<TWeakObjectPtr<UObject>> SelObjs; SelObjs = DetailBuilder.GetSelectedObjects(); for (int32 i = 0; i < SelObjs.Num(); ++i) { UTestObject* pTestObj = Cast<UTestObject>(SelObjs[i]); if (pTestObj != nullptr) { for (TFieldIterator<UProperty> it(pTestObj->GetClass()); it; ++it) { FString PropertyName = it->GetName(); TSharedRef<IPropertyHandle> PropertyHandle = DetailBuilder.GetProperty(PropertyName.GetCharArray().GetData()); IDetailPropertyRow& PropertyRow = DefaultCategory.AddProperty(PropertyHandle); PropertyHandle->MarkResetToDefaultCustomized(); TSharedPtr<SWidget> NameWidget; TSharedPtr<SWidget> ValueWidget; FDetailWidgetRow Row; PropertyRow.GetDefaultWidgets(NameWidget, ValueWidget, Row); const TCHAR* StrName= PropertyName.GetCharArray().GetData(); PropertyRow.CustomWidget() .NameContent() .MinDesiredWidth(Row.NameWidget.MinWidth) .MaxDesiredWidth(Row.NameWidget.MaxWidth) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() [ SNew(SCheckBox) ] + SHorizontalBox::Slot() [ NameWidget.ToSharedRef() ] ] .ValueContent() .MinDesiredWidth(Row.ValueWidget.MinWidth) .MaxDesiredWidth(Row.ValueWidget.MaxWidth) [ ValueWidget.ToSharedRef() ]; } } } }