UE5自定义UMG组件之Panel

最近正在模仿卡牌肉鸽游戏,在于手牌展示的地方需要一定特殊的处理。可以参考炉石传说

image-20220617222918309

image-20220617222931406

卡牌会以一定弧度进行加载。卡片之间存在一定的重叠。如何实现这种效果了?

手牌计算示意图。

image-20220617230857683

在蓝图中去实现这种效果但是不理想。

在编辑器下效果

image-20220617223653508

但是一旦进入运行模式就会出现这样的效果

image-20220617223802923

原因是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的分享

posted @ 2022-06-19 12:56  LDnanchao  阅读(575)  评论(0编辑  收藏  举报