UE5自定义UMG组件之Panel
最近正在模仿卡牌肉鸽游戏,在于手牌展示的地方需要一定特殊的处理。可以参考炉石传说
卡牌会以一定弧度进行加载。卡片之间存在一定的重叠。如何实现这种效果了?
手牌计算示意图。
在蓝图中去实现这种效果但是不理想。
在编辑器下效果
![image-20220617223653508](https://img2022.cnblogs.com/blog/1691837/202206/1691837-20220619125516789-243873206.png)
但是一旦进入运行模式就会出现这样的效果
原因是canvas画布不能对UI组件进行正确的大小变化,同时蓝图对于这种正确的大小描述的函数并没有暴露,因此使用蓝图实现这种手牌效果时不够的。
通过HorizontalBox
可以定位到SBoxPanel
,在其中寻找关于位置设置的关键函数。其实发现
public:
/** Removes a slot from this box panel which contains the specified SWidget
*
* @param SlotWidget The widget to match when searching through the slots
* @returns The index in the children array where the slot was removed and -1 if no slot was found matching the widget
*/
int32 RemoveSlot( const TSharedRef<SWidget>& SlotWidget );
/** Removes all children from the box. */
void ClearChildren();
/** @return the number of slots. */
int32 NumSlots() const { return Children.Num(); }
/** @return if it's a valid index slot index. */
bool IsValidSlotIndex(int32 Index) const { return Children.IsValidIndex(Index); }
public:
//~ Begin SWidget overrides.
virtual void OnArrangeChildren(const FGeometry& AllottedGeometry, FArrangedChildren& ArrangedChildren) const override;
virtual FChildren* GetChildren() override;
protected:
virtual FVector2D ComputeDesiredSize(float) const override;
//~ End SWidget overrides.
/**
* A Box Panel's orientation cannot be changed once it is constructed..
*
* @param InOrientation The orientation of the Box Panel
*/
SBoxPanel( EOrientation InOrientation );
/** The Box Panel's children. */
TPanelChildren<FSlot> Children;
/** The Box Panel's orientation; determined at construct time. */
const EOrientation Orientation;
其实看完了并没有找到准确的函数。
/**
* A BoxPanel contains one child and describes how that child should be arranged on the screen.
*/
class SLATECORE_API SBoxPanel : public SPanel
根据提示去定位到SPanel
/**
* Panels arrange their children in a space described by the AllottedGeometry parameter. The results of the arrangement
* should be returned by appending a FArrangedWidget pair for every child widget. See StackPanel for an example
*
* @param AllottedGeometry The geometry allotted for this widget by its parent.
* @param ArrangedChildren The array to which to add the WidgetGeometries that represent the arranged children.
*/
virtual void OnArrangeChildren( const FGeometry& AllottedGeometry, FArrangedChildren& ArrangedChildren ) const override = 0;
/**
* A Panel's desired size in the space required to arrange of its children on the screen while respecting all of
* the children's desired sizes and any layout-related options specified by the user. See StackPanel for an example.
*
* @return The desired size.
*/
virtual FVector2D ComputeDesiredSize(float) const override = 0;
/**
* All widgets must provide a way to access their children in a layout-agnostic way.
* Panels store their children in Slots, which creates a dilemma. Most panels
* can store their children in a TPanelChildren<Slot>, where the Slot class
* provides layout information about the child it stores. In that case
* GetChildren should simply return the TPanelChildren<Slot>. See StackPanel for an example.
*/
virtual FChildren* GetChildren() override = 0;
这里就能找到核心函数OnArrangeChildren
,由于没有找到注释中的StackPanel
,所有就参考SBoxPanel
的代码进行编写。
定位到核心代码
template<EOrientation Orientation, typename SlotType>
static void ArrangeChildrenAlong(EFlowDirection InLayoutFlow, const TPanelChildren<SlotType>& Children, const FGeometry& AllottedGeometry, FArrangedChildren& ArrangedChildren ){}
这里代码比较长,需要的自己去看源码。
最后贴上完成的代码,自取
链接:https://pan.baidu.com/s/1LV_UvNACZwvwNZ5lQHTfhA?pwd=kjfh
提取码:kjfh
--来自百度网盘超级会员V5的分享