| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- --[[
- readme:has a special mouse event in mouse right button event
- It was used to on the platform expeat window replacing check root node
-
- You can return -1 to continue propagation on the mouse button event but moving.
- mouse move event params
- param = {
- enter = function, --on enter callback
- leave = function, --on leave callback
- inside = function, -- inside moving callback
- }
- mouse button event params
- param = {
- down_r = function, --right button down 函数会传入 touchPos
- up_r = function, --right button up 函数会传入 touchPos
- special_r = function, --special : imitate left button down on mobile 函数会传入 touchPos
- double_l = function, --left button double click 函数会传入 touchPos
- moving = function, -- on moving 函数会传入 touchPos
- scroll = function -- on scroll moving 函数会传入 scrollOff = { x = 0, y = 1} x值目前没变动 Y 值 大于零 向后滚动 小于零 向前
- swallow = number, > 0 stopPropagation
- checkIsVisible = bool,
- CheckTouchEnable = bool,
- moveTouch = bool --该参数目前只用于移动
- }
- **self.registerAllChilderMouseRButtonEvent was only used to add swallow mouse event.
- It will let all children on the father node to get mouse event.
- ]]
- local mouseEventController = class("mouseEventController")
- function mouseEventController:ctor()
- self.onDoubleEvent = false
- self.doubleClickDelayTime = 0.3
- self.lastInsideNodeParam = nil
- self.mouseMoveOffPos = nil
- end
- function mouseEventController:destory()
- if mouseEventController.instance then
- mouseEventController.instance = nil
- end
- end
- function mouseEventController:Inst()
- if not mouseEventController.instance then
- mouseEventController.instance = mouseEventController.new()
- end
- return mouseEventController.instance
- end
- function mouseEventController:GetNodeLastState(node)
- return node._nodeState or false
- end
- function mouseEventController:SetNodeLastState(node, bool)
- if not tolua.isnull(node) then
- node._nodeState = bool
- end
- end
- function mouseEventController:SetLastInsideNode( node, param )
- self.lastInsideNodeParam = nil
- if node and param and not tolua.isnull(node) then
- self.lastInsideNodeParam = {
- sideNode = node,
- param = param
- }
- end
- end
- function mouseEventController:ClearLastInsideNode(node)
- local lastData = self.lastInsideNodeParam
- if lastData and lastData.sideNode and not tolua.isnull(lastData.sideNode) then
- self:SetNodeLastState(lastData.sideNode, false)
- end
- self.lastInsideNodeParam = nil
- end
- function mouseEventController:GetLastInsideNode()
- local lastData = self.lastInsideNodeParam
- if lastData and lastData.sideNode and not tolua.isnull(lastData.sideNode) then
- return lastData.sideNode
- end
- return nil
- end
- function mouseEventController:LeaveLastNode( )
- local lastData = self.lastInsideNodeParam
- if lastData and lastData.sideNode and not tolua.isnull(lastData.sideNode) then
- self:SetNodeLastState(lastData.sideNode, false)
- local param = lastData.param
- if not param or not next(param) then
- return
- end
- local leaveCallBack = param.leave
- if leaveCallBack then
- leaveCallBack()
- end
- end
- end
- function mouseEventController:OnMouseMoveEvent( pos )
- if self.onDoubleEvent then
- if not self.mouseMoveOffPos then
- self.mouseMoveOffPos = pos
- else
- local offPos = math.pow((self.mouseMoveOffPos.x - pos.x), 2) + math.pow((self.mouseMoveOffPos.y - pos.y), 2)
- if offPos > 200 then
- self.onDoubleEvent = false
- self.mouseMoveOffPos = nil
- end
- end
- else
- self.mouseMoveOffPos = nil
- end
- end
- function mouseEventController:registerMouseMoveEvent(node, param)
- local eventCallbacks = param or {}
- if not eventCallbacks.show then
- if not global.MouseEventOpen then
- return false
- end
- end
- local enterCallback = eventCallbacks.enter
- local leaveCallback = eventCallbacks.leave
- local insideCallback = eventCallbacks.inside
- local checkIsVisible = eventCallbacks.checkIsVisible
- local listener = cc.EventListenerMouse:create()
- local eventDispatcher = cc.Director:getInstance():getEventDispatcher()
- local function onMouseMoved(sender)
- if checkIsVisible and (not node:isVisible() or (node:getParent() and not node:getParent():isVisible())) then
- return
- end
- local lastTimeNodeState = self:GetNodeLastState(node)
- local mousePosX = sender:getCursorX()
- local mousePosY = sender:getCursorY()
- local touchPos = {
- x = mousePosX,
- y = mousePosY
- }
- self:OnMouseMoveEvent( touchPos )
- local isInSide = self:checkNodePos(node, touchPos)
- if lastTimeNodeState and isInSide then --一直在内部
- if insideCallback then
- insideCallback()
- end
- self:SetNodeLastState(node, true)
- sender:stopPropagation()
- elseif lastTimeNodeState and not isInSide then --移出
- if leaveCallback then
- leaveCallback()
- end
- self:SetNodeLastState(node, false)
- elseif not lastTimeNodeState and isInSide then --移入
- self:LeaveLastNode()
- if enterCallback then
- enterCallback(touchPos)
- end
- self:SetNodeLastState(node, true)
- self:SetLastInsideNode(node, param)
- sender:stopPropagation()
- end
- end
- listener:registerScriptHandler( onMouseMoved, cc.Handler.EVENT_MOUSE_MOVE )
- eventDispatcher:addEventListenerWithSceneGraphPriority( listener, node )
- end
- function mouseEventController:checkNodePos(node, touchPos)
- if tolua.isnull(node) or not next(touchPos) then
- return false
- end
- local worldPos = node:getWorldPosition()
- local anchor = node:getAnchorPoint()
- local content = node:getContentSize()
- local scaleX = node:getScaleX()
- local scaleY = node:getScaleY()
- local leftPos = worldPos.x - anchor.x * content.width * scaleX
- local rightPos = worldPos.x + (1 - anchor.x) * content.width * scaleX
- local bottomPos = worldPos.y - anchor.y * content.height * scaleY
- local topPos = worldPos.y + (1 - anchor.y) * content.height * scaleY
- local isInSide = false
- if touchPos.x > leftPos and touchPos.x < rightPos and
- touchPos.y > bottomPos and touchPos.y < topPos then
- isInSide = true
- end
- return isInSide
- end
- function mouseEventController:CancelMove(sender, isStop, isReturn)
- local ItemMoveProxy = global.Facade:retrieveProxy(global.ProxyTable.ItemMoveProxy)
- local state = ItemMoveProxy:GetMovingItemState()
- if state then
- global.Facade:sendNotification(global.NoticeTable.Layer_Moved_Cancel)
- if isStop then
- sender:stopPropagation()
- end
- if isReturn then
- return false
- end
- end
- end
- function mouseEventController:registerMouseButtonEvent(node, param)
- local eventCallbacks = param or {}
- local call_down_r = eventCallbacks.down_r
- local call_up_r = eventCallbacks.up_r
- local call_special_r = eventCallbacks.special_r
- local call_double_l = eventCallbacks.double_l
- local call_moving = eventCallbacks.moving
- local call_scrolling = eventCallbacks.scroll
- local swallowMouse = eventCallbacks.swallow or 1
- local checkIsVisible = eventCallbacks.checkIsVisible
- local CheckTouchEnable = eventCallbacks.checkTouchEnable
- local checkSwallowTouches = eventCallbacks.checkSwallowTouches
- local checkVisibleLevel = eventCallbacks.checkVisibleLevel or 2
- local listener = cc.EventListenerMouse:create()
- local eventDispatcher = cc.Director:getInstance():getEventDispatcher()
- local isNeedNodeParam = false
- if not call_scrolling and node.RegisterWin32MouseMoveScrollCall then --GoodsItem注册的鼠标滚动回调
- call_scrolling = node.RegisterWin32MouseMoveScrollCall
- isNeedNodeParam = true
- end
- local function checkVisibleParent(node, level)
- local maxTimes = math.min(level, 6)
- local times = 2
- local parent = node:getParent()
- local visible = true
- local function checkParent(childNode)
- if times >= maxTimes then
- visible = true
- return
- end
- if not tolua.isnull(childNode) then
- local parent = childNode:getParent()
- if not tolua.isnull(parent) then
- if not parent:isVisible() then
- visible = false
- return
- end
- times = times + 1
- checkParent(parent)
- end
- end
- end
- checkParent(parent)
- return visible
- end
- local function onMouseDown(sender)
- if checkIsVisible and (not node:isVisible() or (node:getParent() and not node:getParent():isVisible())) then
- return
- end
- if checkIsVisible and checkVisibleLevel and checkVisibleLevel > 2 and not checkVisibleParent(node, checkVisibleLevel) then
- return
- end
- if CheckTouchEnable and not node:isTouchEnabled() then
- return
- end
- if checkSwallowTouches and not node:isSwallowTouches() then
- return
- end
- local mousePosX = sender:getCursorX()
- local mousePosY = sender:getCursorY()
- local touchPos = {
- x = mousePosX,
- y = mousePosY
- }
- local isInSide = self:checkNodePos(node, touchPos)
- local button = sender:getMouseButton()
- if button == cc.MouseButton.BUTTON_RIGHT then
- if sender.specialRight then
- if isInSide then
- if call_special_r then
- swallowMouse = call_special_r( touchPos ) or 1
- else
- self:CancelMove(sender, true, false)
- end
- if swallowMouse > 0 then
- sender:stopPropagation()
- end
- end
- return
- end
- self:CancelMove(sender, true, true)
- if isInSide then
- if call_down_r then
- if eventCallbacks.moveTouch then
- swallowMouse = call_down_r( touchPos ) or 1
- else
- swallowMouse = call_down_r() or 1
- end
- end
- if swallowMouse > 0 then
- sender:stopPropagation()
- end
- end
- else
- if isInSide then
- if call_double_l then
- if not node._onDoubleClickEvent then
- node._onDoubleClickEvent = true
- self.onDoubleEvent = true
- -- 记录单击触发
- node._clickDelayHandler =
- PerformWithDelayGlobal(
- function()
- if call_special_r then
- swallowMouse = call_special_r( touchPos ) or 1
- end
- node._onDoubleClickEvent = nil
- self.onDoubleEvent = false
- end,
- self.doubleClickDelayTime
- )
- else
- if node._clickDelayHandler then
- UnSchedule(node._clickDelayHandler)
- node._clickDelayHandler = nil
- end
- self:CancelMove(sender, false, false)
-
- swallowMouse = call_double_l( touchPos ) or 1
- node._onDoubleClickEvent = nil
- self.onDoubleEvent = false
- end
- elseif call_special_r then
- if not self.onDoubleEvent then
- swallowMouse = call_special_r( touchPos ) or 1
- end
- end
-
- if swallowMouse > 0 then
- sender:stopPropagation()
- end
- end
- end
- end
- local function onMouseUp(sender)
- global.Facade:sendNotification(global.NoticeTable.Layer_RTouch_State_Change, false)
- if checkIsVisible and (not node:isVisible() or (node:getParent() and not node:getParent():isVisible())) then
- return
- end
- if CheckTouchEnable and not node:isTouchEnabled() then
- return
- end
- if checkSwallowTouches and not node:isSwallowTouches() then
- return
- end
- local button = sender:getMouseButton()
- if button == cc.MouseButton.BUTTON_RIGHT then
- local mousePosX = sender:getCursorX()
- local mousePosY = sender:getCursorY()
- local touchPos = {
- x = mousePosX,
- y = mousePosY
- }
- local isInSide = self:checkNodePos(node, touchPos)
- if isInSide then
- if call_up_r then
- swallowMouse = call_up_r() or 1
- end
- if swallowMouse > 0 then
- sender:stopPropagation()
- end
- end
- end
- end
- if eventCallbacks.moveTouch then --only moving
- local function onMouseMoved(sender)
- if eventCallbacks.moveTouch then
- local mousePosX = sender:getCursorX()
- local mousePosY = sender:getCursorY()
- if call_moving then
- call_moving({x = mousePosX, y = mousePosY})
- end
- end
- end
- listener:registerScriptHandler( onMouseMoved, cc.Handler.EVENT_MOUSE_MOVE )
- end
- if call_scrolling then
- local function omMouseScroll(sender)
- local mousePosX = sender:getCursorX()
- local mousePosY = sender:getCursorY()
- local touchPos = {
- x = mousePosX,
- y = mousePosY
- }
- local isInSide = self:checkNodePos(node, touchPos)
- if isInSide then
- local scrollX = sender:getScrollX()
- local scrollY = sender:getScrollY()
- local scrollData = {
- x = scrollX,
- y = scrollY
- }
- if isNeedNodeParam then
- call_scrolling(node,scrollData)
- else
- call_scrolling(scrollData)
- end
- end
- end
- listener:registerScriptHandler( omMouseScroll, cc.Handler.EVENT_MOUSE_SCROLL)
- end
-
- if node and node.isSignMouListner then
- if node.signRegisterMouseListner then
- eventDispatcher:removeEventListener( node.signRegisterMouseListner )
- node.signRegisterMouseListner = nil
- end
- node.signRegisterMouseListner = listener
- end
- listener:registerScriptHandler( onMouseDown, cc.Handler.EVENT_MOUSE_DOWN )
- listener:registerScriptHandler( onMouseUp, cc.Handler.EVENT_MOUSE_UP )
- eventDispatcher:addEventListenerWithSceneGraphPriority( listener, node )
- end
- -- readme: 本方法只适用于添加吞噬 不建议添加回调
- function mouseEventController:registerAllChilderMouseRButtonEvent(node, param)
- if not node or tolua.isnull(node) then
- return
- end
- local allNode = {}
- local function addToTable(Widget)
- if tolua.iskindof(Widget,"ccui.Widget")then
- table.insert(allNode, Widget)
- end
- end
- addToTable(node)
- local function checkChild(parent)
- local childCount = parent:getChildrenCount()
- if childCount > 0 then
- local childern = parent:getChildren()
- for _,child in pairs(childern) do
- addToTable(child)
- checkChild(child)
- end
- end
- end
- checkChild(node)
- for k,v in pairs(allNode) do
- if not v._noAutoRegisterMouseSwollow then
- self:registerMouseButtonEvent( v ,param )
- end
- end
- end
- return mouseEventController
|