前言
最近在写MessageBox控件,想兼容UMG与c++中调用Slate。略有心得,遂有此文。
动态Slate
首先Slate控件树中创建占位用的NullWidget并使用.Expose()绑定Slot指针,使得可以进行后续操作。
ChildSlot
.VAlign(VAlign_Fill)
.HAlign(HAlign_Fill)
[
SNew(SOverlay)
+ SOverlay::Slot()
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
.Expose(UseMenuSlot) // Expose it to a pointer so we can change the widget at runtime
[
SNullWidget::NullWidget
]
];
之后就可以通过函数对Slot进行操作了,下面演示如何动态添加或者删除Button:
UseMenuSlot->AttachWidget(
InText.Get().IsEmpty() ?
SNullWidget::NullWidget
:
SNew(SButton)
.VAlign(VAlign_Center)
.HAlign(HAlign_Center)
[
SNew(STextBlock)
]
);
支持Expose()的容器
常用的:
SHorizontalBox
SVerticalBox
SOverlay
其他还有若干也支持的
设置指定长度的Widget
有的时候需要让控件保持指定的大小,使用SBox的WidthOverride与HeightOverride即可。其他的控件都不支持这2个属性。
ChildSlot
[
SNew(SBox)
.WidthOverride(256)
.HeightOverride(100)
[
SNew(SButton)
]
];
指定大小控件的UMG与Slate兼容问题
UMG的根节点是一个CanvasPanel(UCanvasPanelSlot)。我认为直接给控件加一个SBox来控制大小的方式不太好。这会使得在UMG中的调整大小变得麻烦。所以我的方法是:使用c++调用Slate控件时,在外面再套一层SConstraintCanvas。
UCanvasPanelSlot本质上是SConstraintCanvas。UMG编辑器中显示的Size实际上是Offset。所以想要指定大小就需要设置Offset的Right与Bottom。
CurrentWidget = SNew(SConstraintCanvas)
+ SConstraintCanvas::Slot()
.Anchors(0.5)
.Alignment(FVector2D(0.5,0.5))
.Offset(FMargin(0,0,500,400))
[
SNew(SCustomWidget)
];
GetGameInstance()->GetGameViewportClient()->AddViewportWidgetContent(CurrentWidget.ToSharedRef());
c++获取UMG控件
UPROPERTY(Meta = (BindWidget)) //直接获取蓝图中的按钮1
UButton* ButtonOne;
bool UFWAffectWidget::Initialize()
{
if (!Super::Initialize()) return false;
//方法1
RootPanel = Cast<UCanvasPanel>(GetRootWidget()); //获取根控件
if (RootPanel)
{
BGImage = Cast<UImage>(RootPanel->GetChildAt(0)); //下标1的BGImage控件
}
//方法2
UButton* ButtonTwo = (UButton*)GetWidgetFromName(TEXT("ButtonTwo"));
//绑定按钮事件方法1:
ButtonOne->OnClicked.__Internal_AddDynamic(this,&UFWAffectWidget::ButtonOneEvent,FName("ButtonOneEvent"));
//绑定事件方法2:委托FScriptDelegate
FScriptDelegate ButTwoDel;
ButTwoDel.BindUFunction(this, "ButtonTwoEvent");
ButtonTwo->OnReleased.Add(ButTwoDel);
return true;
}
参考文章:https://blog.csdn.net/weixin_44200074/article/details/109100521
从UMG控件中获取Slate
TSharedRef<SWidget> UWidget::TakeWidget()
反射
遍历UProperty
for(TFiledIterator<UProperty> It(/*UClass**/);It;++It)
{
UProperty *newProperty=It;
}
根据名称寻找UProperty
UProperty *foundProperty = FindField<UProperty>(/*UClass**/,TEXT("PropertyName"));
Get/Set UProperty
//根据PropertyPath获取属性值
FCachedPropertyPath PropertyPath(FString(TEXT("PropertyName")));
T Value;
ProperthPathHelpers::GetPropertyValue(Object,PropertyPath,Value);
//有获取就有设置
ProperthPathHelpers::SetPropertyValue(Object,PropertyPath,Value);
//还可以获取成String
FString PropertyValueStr;
ProperthPathHelpers::GetPropertyValueAsString(Object,PropertyPath,PropertyValueStr);
//同样,反向也可以
ProperthPathHelpers::SetPropertyValueFromString(Object,PropertyPath,PropertyValueStr);
//实际上,我们平时在UE引擎中复制粘贴属性值就是将属性值获取为String以及从String这只属性值的整个过程。
引用文章:https://zhuanlan.zhihu.com/p/121006155
更多反射技巧:https://bebylon.dev/ue4guide/engine-programming/uobject-reflection/uobject-reflection/