event.phase = "moved" and dragging across multiple buttons

I am creating a level editor for a game which works on a grid system.  I have two sets of defined buttons.

The first set represent the selection of game assets which can go in a grid square.  I’m using these in the same way you might use a colour picker.  You select one of these to select that asset type, ready to “paint” on to the grid.

Then I have the grid buttons, which I want to use to receive the “paint” i.e. the selected asset.

All of my buttons are widget.newButtons.  The problem I have run into is that once a grid button is pressed (and the mouse held down, in the simulator) no further widget buttons seem to be capable of being pressed.  So I can drag my touch across lots of different grid buttons but only the first one registers the touch.

Is there a solution I’m missing?  Can I set buttons so that as I drag my touch across multiple buttons, it triggers all of those buttons that the touch passes over? I don’t want to have to paint terrain one square at a time!

Found a forum post with a similar problem, and the suggested solution (which I feared!) was that you’ve just got to do the maths with event.x and event.y

https://forums.coronalabs.com/topic/39274-ruzzle-clone-is-it-possible-with-corona-sdk/

As it happens, that’s not too bad for my grid, but it strikes me as an inadequate and cumbersome solution for any button combo that’s more complicated (or even, dare I say it, moving buttons/targets?)

Is this the only solution do people know?

Hi @epicurus101,

Widget buttons can detect all phases (including “moved”) if you use the “onEvent” type of listener for it. See the documentation on this point:

https://docs.coronalabs.com/api/library/widget/newButton.html

Best regards,

Brent

Hi Brent, I realise widgets can detect different phases, but what a button can’t do is detect if a touch is moving over it if the touch didn’t originate on that button.  The following code illustrates my point (the dimensions are for a standard tablet).

If you press and hold button1 the screen goes red.  Press and hold button2 and the screen goes green.  But you can’t swipe a touch from button1 to button2 and watch the screen go from red to green.  While it’s in the original event.phase = “moved” it’s only registering it for button1.  I realise there are work arounds but I just wanted to check absolutely that this is a fixed limitation (or “feature”!) of widget buttons.

[lua]

widget = require(“widget”)

background = display.newRect(display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight)

background.fill = {1,1,1}

function handleButton1( event )

  if event.phase == “began” or event.phase == “moved” then

    background.fill = {1,0,0}

  else

    background.fill = {1,1,1}

  end

end

button1 = widget.newButton{

  label = “Button 1”,

  onEvent = button1Event,

  shape=“rect”,

  x = 250,

  y = display.contentCenterY,

  width = 200,

  height = 200,

  fillColor = { default={ 0.3, 0.3, 0.3, 1 }, over={ 0.6, 0.6, 0.6, 1 } },

  onEvent = handleButton1

}

function handleButton2( event )

  if event.phase == “began” or event.phase == “moved” then

    background.fill = {0,1,0}

  else

    background.fill = {1,1,1}

  end

end

button2 = widget.newButton{

  label = “Button 2”,

  onEvent = button2Event,

  shape=“rect”,

  x = display.contentWidth - 250,

  y = display.contentCenterY,

  width = 200,

  height = 200,

  fillColor = { default={ 0.3, 0.3, 0.3, 1 }, over={ 0.6, 0.6, 0.6, 1 } },

  onEvent = handleButton2

}

[/lua]

Hi,

I’m at work now so I can’t test, but once you’ve handled the begin touch event and painted the grid button with the currently selected asset, could you then dispatch a touch event with phase == “ended” to the button widget to make it deselect itself?

Something along the lines of this in your handler:

function handleButton2( event ) if event.phase == "began" background.fill = {0,1,0} local levent = { name = "faketouchended", type = "touch", phase = "ended", target = event.target } event.target:dispatchEvent( levent ) else -- ended and moved here do nothing since we already painted the square. end

This is a complete guess btw  :smiley:

Hi @epicurus101,

Personally, I wouldn’t use widget buttons for this… it just seems like a slight “overkill” for what you’re doing with them. I’d just create vector rectangles and build my own touch detection on them.

Brent

Found a forum post with a similar problem, and the suggested solution (which I feared!) was that you’ve just got to do the maths with event.x and event.y

https://forums.coronalabs.com/topic/39274-ruzzle-clone-is-it-possible-with-corona-sdk/

As it happens, that’s not too bad for my grid, but it strikes me as an inadequate and cumbersome solution for any button combo that’s more complicated (or even, dare I say it, moving buttons/targets?)

Is this the only solution do people know?

Hi @epicurus101,

Widget buttons can detect all phases (including “moved”) if you use the “onEvent” type of listener for it. See the documentation on this point:

https://docs.coronalabs.com/api/library/widget/newButton.html

Best regards,

Brent

Hi Brent, I realise widgets can detect different phases, but what a button can’t do is detect if a touch is moving over it if the touch didn’t originate on that button.  The following code illustrates my point (the dimensions are for a standard tablet).

If you press and hold button1 the screen goes red.  Press and hold button2 and the screen goes green.  But you can’t swipe a touch from button1 to button2 and watch the screen go from red to green.  While it’s in the original event.phase = “moved” it’s only registering it for button1.  I realise there are work arounds but I just wanted to check absolutely that this is a fixed limitation (or “feature”!) of widget buttons.

[lua]

widget = require(“widget”)

background = display.newRect(display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight)

background.fill = {1,1,1}

function handleButton1( event )

  if event.phase == “began” or event.phase == “moved” then

    background.fill = {1,0,0}

  else

    background.fill = {1,1,1}

  end

end

button1 = widget.newButton{

  label = “Button 1”,

  onEvent = button1Event,

  shape=“rect”,

  x = 250,

  y = display.contentCenterY,

  width = 200,

  height = 200,

  fillColor = { default={ 0.3, 0.3, 0.3, 1 }, over={ 0.6, 0.6, 0.6, 1 } },

  onEvent = handleButton1

}

function handleButton2( event )

  if event.phase == “began” or event.phase == “moved” then

    background.fill = {0,1,0}

  else

    background.fill = {1,1,1}

  end

end

button2 = widget.newButton{

  label = “Button 2”,

  onEvent = button2Event,

  shape=“rect”,

  x = display.contentWidth - 250,

  y = display.contentCenterY,

  width = 200,

  height = 200,

  fillColor = { default={ 0.3, 0.3, 0.3, 1 }, over={ 0.6, 0.6, 0.6, 1 } },

  onEvent = handleButton2

}

[/lua]

Hi,

I’m at work now so I can’t test, but once you’ve handled the begin touch event and painted the grid button with the currently selected asset, could you then dispatch a touch event with phase == “ended” to the button widget to make it deselect itself?

Something along the lines of this in your handler:

function handleButton2( event ) if event.phase == "began" background.fill = {0,1,0} local levent = { name = "faketouchended", type = "touch", phase = "ended", target = event.target } event.target:dispatchEvent( levent ) else -- ended and moved here do nothing since we already painted the square. end

This is a complete guess btw  :smiley:

Hi @epicurus101,

Personally, I wouldn’t use widget buttons for this… it just seems like a slight “overkill” for what you’re doing with them. I’d just create vector rectangles and build my own touch detection on them.

Brent