Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
How to add multitouch support for the Button class? — Gideros Forum

How to add multitouch support for the Button class?

andreeibandreeib Member
edited June 2012 in General questions
Hi guys, I'm new here and I barely started using Gideros but already have a project 70% finished, the thing is I have a small problem.

I created some buttons using a slightly modified version of the Button class from the Gideros github account. I have three buttons, two used for controlling the direction and one used for an action. If you look down at the code of my Button class you can see I added a new event that is dispatched continuously if the button is hold pressed.

The problem is that if the user holds pressed a direction button and tries to press the action button at the same time it doesn't work, it seems the Button class was not made to support multitouch.

My question is how can I allow the user to press more than one button at a time?

Thanks for the help,
Andrei


This is my Button class:
--[[
A generic button class
 
This code is MIT licensed, see <a href="http://www.opensource.org/licenses/mit-license.php" rel="nofollow">http://www.opensource.org/licenses/mit-license.php</a>
(C) 2010 - 2011 Gideros Mobile 
]]
 
Button = gideros.class(Sprite)
 
function Button:init(upState, downState)
	self.upState = upState
	self.downState = downState
 
	self.focus = false
 
	-- set the visual state as "up"
	self:updateVisualState(false)
 
	-- register to all mouse and touch events
	self:addEventListener(Event.MOUSE_DOWN, self.onMouseDown, self)
	self:addEventListener(Event.MOUSE_MOVE, self.onMouseMove, self)
	self:addEventListener(Event.MOUSE_UP, self.onMouseUp, self)
 
	self:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
	self:addEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self)
	self:addEventListener(Event.TOUCHES_END, self.onTouchesEnd, self)
	self:addEventListener(Event.TOUCHES_CANCEL, self.onTouchesCancel, self)
 
	-- enter frame event
	self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
end
 
function Button:onMouseDown(event)
	if self:hitTestPoint(event.x, event.y) then
		self.focus = true
		self:updateVisualState(true)
		self:dispatchEvent(Event.new('clickDown'))
		event:stopPropagation()
	end
end
 
function Button:onMouseMove(event)
	if self.focus then
		if not self:hitTestPoint(event.x, event.y) then	
			self.focus = false
			self:updateVisualState(false)
		end
		event:stopPropagation()
	else
		if self:hitTestPoint(event.x, event.y) then	
			self.focus = true
			self:updateVisualState(true)
		end
	end
end
 
function Button:onMouseUp(event)
	if self.focus then
		self.focus = false
		self:updateVisualState(false)
		self:dispatchEvent(Event.new('clickUp'))
		event:stopPropagation()
	end
end
 
-- if button is on focus, stop propagation of touch events
function Button:onTouchesBegin(event)
	if self.focus then
		event:stopPropagation()
	end
end
 
-- if button is on focus, stop propagation of touch events
function Button:onTouchesMove(event)
	if self.focus then
		event:stopPropagation()
	end
end
 
-- if button is on focus, stop propagation of touch events
function Button:onTouchesEnd(event)
	if self.focus then
		event:stopPropagation()
	end
end
 
-- if touches are cancelled, reset the state of the button
function Button:onTouchesCancel(event)
	if self.focus then
		self.focus = false;
		self:updateVisualState(false)
		event:stopPropagation()
	end
end
 
-- if the button is focused then dispatch the clickHold event
function Button:onEnterFrame(event)
	if self.focus then
		self:dispatchEvent(Event.new('clickHold'))
	end
end
 
-- if state is true show downState else show upState
function Button:updateVisualState(state)
	if state then
		if self:contains(self.upState) then
			self:removeChild(self.upState)
		end
 
		if not self:contains(self.downState) then
			self:addChild(self.downState)
		end
	else
		if self:contains(self.downState) then
			self:removeChild(self.downState)
		end
 
		if not self:contains(self.upState) then
			self:addChild(self.upState)
		end
	end
end

Likes: Tom2012

+1 -1 (+1 / -0 )Share on Facebook

Comments

  • ar2rsawseenar2rsawseen Maintainer
    Haven't tried that, but from the first look, you can try swap contents of
    function Button:onMouseDown(event) with function Button:onTouchesBegin(event) then
    function Button:onMouseMove(event) with function Button:onTouchesMove(event) and
    function Button:onMouseUp(event) with function Button:onTouchesEnd(event)

    Only difference, that inside touch events you should use event.touch.x and event.touch.y instead of event.x and event.y.

    As I said, I haven't tried, but It should/might work :D
  • atilimatilim Maintainer
    edited June 2012
    Addition to @ar2rsawseen,

    the code,
    -- if the button is focused then dispatch the clickHold event
    function Button:onEnterFrame(event)
    	if self.focus then
    		self:dispatchEvent(Event.new('clickHold'))
    	end
    end
    creates an Event object at each frame for each focused button and therefore consumes memory continuously. Instead, I would create a function like isHold or isFocus and return the value of self.focus:
    function Button:isFocus()
        return self.focus
    end
    Also if you want to dispatch an event many times, you can create the Event object once and dispatch many. This optimization is heavily used in Gideros internally (for ENTER_FRAME, mouse and touch events, etc)

    Also you'll love http://www.tntparticlesengine.com/?cat=13 :)
  • You need to look at the multi touch example code - I don't think you can use the "mouse" events if your intending to support multi-touch.
    WhiteTree Games - Home, home on the web, where the bits and bytes they do play!
    #MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
  • Thanks @ar2rsawseen it worked great, the only problem is that in the GiderosPlayer the clicks don't work now, just on my phone.

    I made the optimization you sugested @atilim, thanks.
  • Unfortunately, multi-touches only work on a real device. There is no way to emulate multi-touch on a desktop machine.
  • My question is, can you only use "onMouse" events? They both work in
    the simulator and on the iPhone, so why should you use "onTouches"?

    Regards,

    Marc
  • You have to use them for simultaneous touches, allowing gestures etc.
  • I also tried the same code as provided here but somehow when I click one of the buttons on screen, others dont receive the touch. I even disabled stop:propogation's but no effect. Any idea why ?
  • I've also got some troubles with multi-touch button, so I try to approach a diferrent way. http://www.giderosmobile.com/forum/discussion/1333/multitouch-ui

    hope that it's useful

    Likes: phongtt

    +1 -1 (+1 / -0 )Share on Facebook
  • bowerandybowerandy Guru
    edited July 2012
    Folks, I had made some modifications to the standard Gideros button class but, until recently this didn't support multi-touch either. However, just this morning I needed mutli-touch functionality so here's what I did.

    Basically, the idea is to do most of the processing inside touch event handlers after first taking account of the particular touch id we are working with. However, in order that the button still works inside the desktop player I also have mouse handlers that "fake" up a touch event (with id=0) so I can use the same touch code for either case. I hope that makes sense.

    The code below is a snippet from my own button class but it should be easily adaptable back to the original Gideros button if required.

    best regards,
     
    function BhButton:onMouseDown(event)
    	-- Fake a touch event with id 0, this allows buttons to work in the simulator
    	-- that doesn't normally understand touch events.	
    	event.touch={ x=event.x, y=event.y, id=0}
    	self:onTouchesBegin(event)	
    end
     
    function BhButton:onMouseMove(event)
    	-- Fake a touch event with id 0, this allows buttons to work in the simulator
    	-- that doesn't normally understand touch events.	
    	event.touch={ x=event.x, y=event.y, id=0}
    	self:onTouchesMove(event)	
    end
     
    function BhButton:onMouseUp(event)
    	-- Fake a touch event with id 0, this allows buttons to work in the simulator
    	-- that doesn't normally understand touch events.	
    	event.touch={ x=event.x, y=event.y, id=0}
    	self:onTouchesEnd(event)	
    end
     
    function BhButton:onTouchesBegin(event)
    	if self.touchId==nil and  self.isEnabled and self:isVisibleDeeply() and self:hitTestPoint(event.touch.x, event.touch.y) then
    		self.touchId=event.touch.id
    		self.isDown = true
    		self:updateVisualState()
    		event:stopPropagation()
    	end
    end
     
    function BhButton:onTouchesMove(event)
    	if self.touchId==event.touch.id then
    		if not self:hitTestPoint(event.touch.x, event.touch.y) then	
    			self.touchId=nil
    			self.isDown = false
    			self:updateVisualState()
    		end
    		event:stopPropagation()
    	end
    end
     
    function BhButton:onTouchesEnd(event)
    	if self.touchId==event.touch.id then
    		self.touchId=nil
    		self.isDown = false
    		self:updateVisualState()
     
    		-- Button is clicked, dispatch "click" event
    		local event=Event.new("click")
    		event.target=self
    		self:dispatchEvent(event)	
    		event:stopPropagation()
    	end
    end
     
    -- if touches are cancelled, reset the state of the button
    function BhButton:onTouchesCancel(event)
    	if self.touchId==event.touch.id  then
    		self.touchId=nil
    		self.isDown = false
    		self:updateVisualState()
    		event:stopPropagation()
    	end
    end
Sign In or Register to comment.