UE学习笔记--实现一套通用的筛选器Filter

前言

Filter 筛选器,是个很常见的工具,在各种游戏引擎中都有对应的工具。
比如 UE 的 Content Browser。
在这里插入图片描述
这里我们不讨论 UI 层面的实现,只按照 Filter 的逻辑,实现相关的逻辑。

原理分析

如上图,UE 的筛选器,和其他概念的筛选器,根本就是一大堆枚举状态的融合。
比如有一个 enum,有各种的标志。

enum class EFlags: uint32
{
	None = 0
	New,
	Pending,
	Running,
	Stop
};

如果想让一个 enum 对象拥有多个 Flag 呢?比如 New、Pending、Stop。
这个时候就需要使用二进制了。
我们可以指定

New 		= 0001
Pending		= 0010
Running 	= 0100
Stop 		= 1000

如果我们想筛选出既是 New 的,又是 Stop 的,只需要把他们对应的数值 按位或,也就是 | 就可以了。

New | Stop = 0001 | 1000 = 1001

代码实现

这里使用的是 UE C++

先定义一个 Flags 的模板类,重载对应的运算符。

template<typename Enum>
struct TEnumClassFlagsHelper
{
	// 确保 Enum 是一个枚举类
	static_assert(TIsEnumClass<Enum>::Value, "Enum must be an enum class type");

	// 定义按位操作符
	friend Enum operator|(Enum lhs, Enum rhs)
	{
		return static_cast<Enum>(static_cast<std::underlying_type_t<Enum>>(lhs) | static_cast<std::underlying_type_t<Enum>>(rhs));
	}

	friend Enum operator&(Enum lhs, Enum rhs)
	{
		return static_cast<Enum>(static_cast<std::underlying_type_t<Enum>>(lhs) & static_cast<std::underlying_type_t<Enum>>(rhs));
	}

	friend Enum operator~(Enum lhs)
	{
		return static_cast<Enum>(~static_cast<std::underlying_type_t<Enum>>(lhs));
	}

	friend Enum& operator|=(Enum& lhs, Enum rhs)
	{
		lhs = lhs | rhs;
		return lhs;
	}

	friend Enum& operator&=(Enum& lhs, Enum rhs)
	{
		lhs = lhs & rhs;
		return lhs;
	}
};

再写操作二进制的子类。

当然你们也可以把两个类的内容合在一起。我这样写是为了方便其他不适用二进制Flags的枚举继承自TEnumClassFlagsHelper,就不用每个 enum 都写对应的重载了。

template<class Enum>
class TBitwiseFlags : TEnumClassFlagsHelper<Enum>
{
	// 确保继承自 uint32
	static_assert(std::is_same<typename std::underlying_type<Enum>::type, uint32>::value, "The underlying type of Enum must be uint32");
	
public:
	bool HasAnyFlags(Enum CheckFlags) { return static_cast<uint32>(CurrentFlags & CheckFlags) != 0; }

	bool EqualsFlags(Enum CheckFlags) { return CurrentFlags == CheckFlags; }

	void AddFlags(Enum AddedFlags) { CurrentFlags |= AddedFlags; }
	
	void RemoveFlags(Enum RemovedFlags) { CurrentFlags &= ~RemovedFlags; }

	Enum LowFlag() { return CurrentFlags & -CurrentFlags; }
	
	void SetCurrentFlags(Enum NewFlags) { CurrentFlags = NewFlags; }

	Enum GetCurrentFlags() { return CurrentFlags; }

private:
	Enum CurrentFlags;
};

最后再写对应的类。


enum class EFlags: uint32
{
	None = 0
	New,
	Pending,
	Running,
	Stop
};

class TestClass
{
	TBitwiseFlags<EFlags> CurrentFlags;
};

用起来就很简单了。

CurrentFlags.SetCurrentFlags(EFlags::None);

CurrentFlags.HasAnyFlags(EFlags::New | EFlags::Stop);

CurrentFlags.AddFlags(EFlags::New | EFlags::Stop);
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就一枚小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值