Lite2D UI编辑器3 自动类型映射解析属性
主要是对上篇 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;} };
