-- 实现自动绑定数据的函数 -- @netObject 需要绑定添加事件的对象 -- @valueName 需要绑定哪个变量名 -- @propertyNameOrFunc , 当添加事件发生时的回调或设置什么属性,回调格式是func(cc.Node , value); -- @return index , unbinder index是用来调用Ref:unbind函数的。unbinder是自动调用unbind函数 function cc.Node:bind(netObject , valueName , propertyNameOrFunc) local onPropChange; local typeP = type(propertyNameOrFunc); if typeP == "function" then onPropChange = function(key , value) propertyNameOrFunc(self , value); end elseif typeP == "string" then local function onChange(key , value) self[propertyNameOrFunc](self , value); end onPropChange = onChange else error("绑定数据" .. tostring(valueName) .. "时第三个参数错误,必须是属性名或函数" .. tostring(propertyNameOrFunc)) return; end local index = netObject:bind(valueName , onPropChange); local unbinder = self:_autoUnbind(netObject , valueName , index); return index , unbinder; end -- 跟bind一样,但第一次调用时不回调 function cc.Node:bindOnUpdate(netObject , valueName , propertyNameOrFunc) local firstRun = true; local function callback(...) if firstRun then firstRun = false; return; end local onPropChange; local typeP = type(propertyNameOrFunc); if typeP == "function" then onPropChange = function(key , value) propertyNameOrFunc(self , value); end elseif typeP == "string" then onPropChange = function(key , value) self[propertyNameOrFunc](self , value); end else error("绑定数据" .. tostring(valueName) .. "时第三个参数错误,必须是属性名或函数" .. tostring(propertyNameOrFunc)) return; end onPropChange(...); end return self:bind(netObject , valueName , callback) end function cc.Node:getLuaData(key) return self[key]; end local function autoUnbindAll(binds) for i , v in pairs(binds) do for ii , vv in pairs(v) do for iii , vvv in pairs(vv) do vvv(); end end end end function cc.Node:setLuaData(key , value) if self[key] == nil then if value ~= nil then local function onUnbind(node , eventType) if eventType == cc.NodeEvent.OnCleanup then local value = self[key]; if value then autoUnbindAll(value); self[key] = nil; end end end self.UnbindListener = self:addNodeEventListener(onUnbind); end else if value == nil then if self.UnbindListener then --self:removeNodeEventListener(self.UnbindListener); self.UnbindListener = nil; end end end self[key] = value; end -- 解绑数据 --[[ 用法: -- 绑定,并返回这个对象的绑定索引 local index = label:bind(game.actor , "level" , "String"); -- 解绑 label:unbind(game.actor , index); --]] function cc.Node:unbind(netObject , bindName, index) local allbinds = self:getLuaData("_autoBinds") if allbinds == nil then return false; end local bindsList = allbinds[netObject]; if bindsList == nil then return false; end -- 如果已经绑定过,就解除绑定 local binds = bindsList[bindName]; if not binds then return false; end; local unbinder = binds[index]; if unbinder then unbinder() return true; else return false; end end -- 解除所有绑定 function cc.Node:unbindAll() local allbinds = self:getLuaData("_autoBinds") if allbinds == nil then return false; end for i , v in pairs(allbinds) do for ii , vv in pairs(v) do for iii , vvv in pairs(vv) do vvv(); end; end end self:setLuaData("_autoBinds" , nil); end function cc.Node:__autoUnbind(object , bindName , bindIndex , unbind) local allbinds = self:getLuaData("_autoBinds") if allbinds == nil then allbinds = {} self:setLuaData("_autoBinds" , allbinds); end local bindsList = allbinds[object]; if bindsList == nil then bindsList = {} allbinds[object] = bindsList end -- 如果已经绑定过,就先解除绑定 bindsList[bindName] = bindsList[bindName] or {}; local unbinder = bindsList[bindName][bindIndex]; if unbinder then unbinder() end bindsList[bindName][bindIndex] = unbind; return unbind; end -- 自动在CCObject对象析构时解除绑定 function cc.Node:_autoUnbind(netObject , bindName , bindIndex) local function unbind() netObject:unbind(bindIndex); end return self:__autoUnbind(netObject , bindName , bindIndex , unbind); end -- 实现自动绑定数据的函数 -- @netObject , 需要绑定添加事件的对象 -- @func , 当添加事件发生时的回调,回调格式是func(cc.Node , key , value); function cc.Node:bindAdd(netObject , func) local onAdd = function(key , value) func(self , key , value); end if type(func) ~= "function" then error("绑定添加事件时参数错误,必须是属性名或函数" .. tostring(func)) return; end local index = netObject:bindAdd(onAdd); self:_autoUnbind(netObject , "__add" , index); return index; end -- 实现自动绑定数据的函数 -- @netObject , 需要绑定元素移除事件的对象 -- @func , 当元素移除事件发生时的回调,回调格式是func(cc.Node , key , value); function cc.Node:bindRemove(netObject , func) local onRemove = function(key , value) func(self , key , value); end if type(func) ~= "function" then error("绑定移除事件时参数错误,必须是属性名或函数" .. tostring(func)) return; end local index = netObject:bindRemove(onRemove); self:_autoUnbind(netObject , "__remove" , index); return index; end -- 实现一个map下绑定某个key下的subKey的绑定,如果不传subKey就是绑定某个key -- 用例 ui:bindMapObject(app.storeHouse.Goods,goodsId,"num",updateGoodsNum); function cc.Node:bindMapObject(mapObject,key,subKey,func) if type(func) ~= "function" then error("绑定更新事件时参数错误,必须是属性名或函数" .. tostring(func)) return; end if(mapObject[key])then if(subKey)then self:bind(mapObject[key],subKey,func); else self:bind(mapObject,key,func); end else func(self,0) end self:bindAdd(mapObject,function(ui,addKey,value) if(addKey==key)then if(subKey)then func(self,value[subKey]); self:bind(mapObject[key],subKey,func); else func(self,value); self:bind(mapObject,key,func); end end end) self:bindRemove(mapObject,function(ui,removeKey,value) if(removeKey==key)then func(self,0); end end) end -- 实现自定绑定updateTo的调用 -- @netObject , 需要绑定被修改的对象 -- @func , 当添加事件发生时的回调,回调格式是func(cc.Node , netObject); function cc.Node:bindUpdateTo(netObject , func) local onUpdate = function(netObject) func(self , netObject); end if type(func) ~= "function" then error("绑定更新事件时参数错误,必须是属性名或函数" .. tostring(func)) return; end local index = netObject:bindUpdateTo(onUpdate); self:_autoUnbind(netObject , "__updateTo" , index); return index; end -- 实现自动绑定数据的函数 -- @netObject , 需要绑定添加事件的对象 -- @func , 当添加事件发生时的回调,回调格式是func(cc.Node , key , value); function cc.Node:bindUpdate(netObject , func) local onUpdate = function(key , value) func(self , key , value); end if type(func) ~= "function" then error("绑定添加事件时参数错误,必须是属性名或函数" .. tostring(func)) return; end local index = netObject:bindUpdate(onUpdate); self:_autoUnbind(netObject , "__update" , index); return index; end -- 绑定到NetObject数组 function cc.Node:initWithNetObject(netObject , createFunction) local items = {}; self.Items = items; local function onAdd(self , key , value) local node = createFunction(key , value); if node then self:addChild(node); if node:hasClip("fadeIn") then node:playClip("fadeIn"); end end items[key] = node; end self:bindAdd(netObject , onAdd); local function onRemove(self , key , value) local node = items[key]; if node then if node:hasClip("fadeOut") then local function onPlayEnd() self:removeChild(node) end node:playClip("fadeOut" , onPlayEnd); else self:removeChild(node) end end end self:bindRemove(netObject , onRemove); self:removeAllChildren(); for i , v in pairs(netObject) do onAdd(self , i , v); end end -- 绑定事件派发,并在当前对象释放时自动解绑 function cc.Node:bindEvent(eventProtocol , eventName , listener) local handle = eventProtocol:addEventListener(eventName , listener); local function unbind() eventProtocol:removeEventListener(eventName , handle); end self:__autoUnbind(eventProtocol , eventName , handle , unbind); return handle end -- 绑定屏幕大小改变 function cc.Node:bindScreenSize(listener) local function onChanged() local glView = cc.Director:getInstance():getOpenGLView(); listener(glView:getFrameSize() , cc.Director:getInstance():getWinSize()); end local lis = cc.EventListenerCustom:create("applicationScreenSizeChanged" , onChanged); cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(lis , 1); local function unbind() if not tolua.isnull(lis) then cc.Director:getInstance():getEventDispatcher():removeEventListener(lis); end end self:__autoUnbind(cc.Director:getInstance():getEventDispatcher() , "applicationScreenSizeChanged" , lis , unbind); onChanged(); return lis; end -- 发送网络消息,并在当前对象释放时自动解绑 -- 有四种用法: --[[ 对于定义了sender的协议来说,这样用 ui:sendMsg(app.hero , "addHeroExp" , { heroId = self.HeroInfo.heroId }); ui:sendMsg(app.hero , "addHeroExp" , { heroId = self.HeroInfo.heroId } , function()showTooltip("升级成功")end); 对于没有定义sender的协议来说,这样用 ui:sendMsg(app.hero , "getHeroList"); ui:sendMsg(app.hero , "getHeroList" , function()showTooltip("拉取英雄列表成功")end); --]] function cc.Node:sendMsg(netProtocol , msgName , argsOrResponseFunction , responseFunction) local function onResponse(...) if type(argsOrResponseFunction) == "function" then argsOrResponseFunction(...); elseif responseFunction then responseFunction(...); end end if type(argsOrResponseFunction) == "function" or argsOrResponseFunction == nil then netProtocol[msgName](netProtocol , onResponse); else netProtocol[msgName](netProtocol , argsOrResponseFunction , onResponse); end do return end -- 界面析构时不再接受回调 local function unbind() -- 这里不能关闭等待窗口,等网络消息返回时才可以关闭等待窗口 --app.waitDialogManager:closeWaitDialog(); argsOrResponseFunction = nil responseFunction = nil end self:__autoUnbind(netProtocol, msgName, onResponse, unbind); end