主要是对上篇 Lite2D UI编辑器2 的属性解析优化
利用map 吧 函数名字和 属性关联起来 达到自动关联的目的
通过宏 来映射,插入关联函数,当然完整版本还需要加上不同的参数的宏,如果参数是对象的话,那么还需要额外处理
来可以用静态数组 和宏 来加快查找速度 ,因为函数地址是静态的
迭代1:
static std::unordered_map<string, std::function<void(float )>> _attrs;
#define REGISTER_MAP_ATTR_FLOAT(MAP,KEY,FUNC,TARGET)\
MAP.insert(std::make_pair(string(KEY), std::bind(&FUNC,TARGET,std::placeholders::_1)));
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
Layer::init();
Sprite *s = Sprite::create("1.png");
REGISTER_MAP_ATTR_FLOAT(_attrs, "x", Node::setPositionX, s);
REGISTER_MAP_ATTR_FLOAT(_attrs, "y", Node::setPositionY, s);
std::map<string, float> _at;
_at.insert(std::make_pair( "x", 100.0f));
_at.insert(std::make_pair("y", 100.0f));
for (auto it = _attrs.begin(); it != _attrs.end(); ++it)
{
auto key = (*it).first;
(*it).second(_at[key]);
}
this->addChild(s);
return true;
}
迭代2:吧参数模板化,实现统一接口,达到数据类型和绑定的函数参数无关,实现真正的自动映射
class Wapper
{
public:
Wapper(){}
Wapper(int arg)
{
this->i = arg;
this->_type = TYPE::INT;
}
Wapper(float arg)
{
this->f = arg;
this->_type = TYPE::FLOAT;
}
Wapper(bool arg)
{
this->b = arg;
this->_type = TYPE::BOOL;
}
Wapper(double arg)
{
this->d = arg;
this->_type = TYPE::DOUBLE;
}
int toInt()
{
if (this->_type == TYPE::INT)
{
return this->i;
}
if (this->_type == TYPE::FLOAT)
{
return (int)(this->f);
}
if (this->_type == TYPE::DOUBLE)
{
return (int)(this->d);
}
if (this->_type == TYPE::BOOL)
{
return this->b == 0 ? false : true;
}
}
float toFloat()
{
if (this->_type == TYPE::INT)
{
return (float)this->i;
}
if (this->_type == TYPE::FLOAT)
{
return (this->f);
}
if (this->_type == TYPE::DOUBLE)
{
return (float)(this->d);
}
if (this->_type == TYPE::BOOL)
{
return this->b == false ? 0.0f : 1.0f;
}
}
double toDouble()
{
if (this->_type == TYPE::INT)
{
return (double)this->i;
}
if (this->_type == TYPE::FLOAT)
{
return (double)this->f;
}
if (this->_type == TYPE::DOUBLE)
{
return this->d;
}
if (this->_type == TYPE::BOOL)
{
return this->b == false ? 0.0 : 1.0;
}
}
bool toBool()
{
if (this->_type == TYPE::INT)
{
return this->i == 0 ? false : true;;
}
if (this->_type == TYPE::FLOAT)
{
return this->f < 0.0000000001 ? false : true;;
}
if (this->_type == TYPE::DOUBLE)
{
return this->d < 0.0000000001 ? false : true;;
}
if (this->_type == TYPE::BOOL)
{
return this->b;
}
}
union
{
int i = 0;
float f;
bool b;
double d;
};
enum class TYPE
{
INT,
FLOAT,
DOUBLE,
BOOL
};
operator int() { return this->toInt(); }
operator float() { return this->toFloat(); }
operator bool() { return this->toBool(); }
operator double() { return this->toDouble(); }
private:
TYPE _type;
};
#define REGISTER_MAP_ATTR(MAP,KEY,FUNC,TARGET) \
MAP.insert(std::make_pair(string(KEY), \
std::bind(&FUNC, TARGET, std::placeholders::_1)));
static std::unordered_map<string, std::function<void(Wapper)>> _attrsAll;
template<class TT, class T >
void invoke(TT & func, T arg)
{
func((T)arg);
}
bool HelloWorld::init()
{
Layer::init();
Sprite *s = Sprite::create("1.png");
//注册属性 和对应的函数映射
REGISTER_MAP_ATTR(_attrsAll, "x", Node::setPositionX, s);
REGISTER_MAP_ATTR(_attrsAll, "y", Node::setPositionY, s);
REGISTER_MAP_ATTR(_attrsAll, "flipy", Sprite::setFlippedY, s);
// 添加属性描述
std::map<string, Wapper> _at;
_at.insert(std::make_pair("x", 300.0f));
_at.insert(std::make_pair("y", 100.0f));
_at.insert(std::make_pair("flipy", true));
//遍历解析属性
for (auto it = _attrsAll.begin(); it != _attrsAll.end(); ++it)
{
auto key = (*it).first;
auto value = (*it).second;
invoke((*it).second, _at[key]);
}
this->addChild(s);
return true;
}
在这里的实际情况中,Wapper 还可以简化为,因为原本参数类型 就是 实际的转换类型,也就是 不存在例如int转float的情况,前提是 属性参数类型和 映射的函数参数类型一致
class Wapper
{
public:
Wapper(){}
Wapper(int arg)
{
this->i = arg;
}
Wapper(float arg)
{
this->f = arg;
}
Wapper(bool arg)
{
this->b = arg;
}
union
{
int i;
float f;
bool b;
};
operator int() const{return i;}
operator float() const{return f;}
operator bool() const{return b;}
};