Code Monkey home page Code Monkey logo

defold-input's Introduction

Build Status

Defold-Input

Defold-Input contains a number of different Lua modules and scripts to simplify input related operations such as gestures detection, user configurable key bindings, input state handling and dragging/clicking game objects.

Setup

You can use the extension in your own project by adding this project as a Defold library dependency. Open your game.project file and in the dependencies field under project add:

https://github.com/britzl/defold-input/archive/master.zip

Or point to the ZIP file of a specific release.

Try HTML5 Demo

You can try an HTML5 demo of Defold-Input here: https://britzl.github.io/Defold-Input/

Gooey

For a complete and easily skinnable UI system that supports buttons, checkboxes, input fields and lists please take a look at Gooey.

defold-input's People

Contributors

aglitchman avatar azurac avatar britzl avatar bsdguyshawn avatar jerakin avatar sandstedt avatar trevortni avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

defold-input's Issues

Suggestion: Event-only, axis-bound, and abortable/fixed-distance dragging

Three related ideas to make it easier to get a similar feel to swapping tiles in Candy Crush (which swaps tiles immediately on dragging half a tile, only vertically or horizontally, aborting the drag after):

First, if a flag can be set so that dragging only informs the object that a drag happened, without moving the object, then the object can handle custom responses to dragging.

For example, a flag to bind to the nearest axis would allow horizontal or vertical dragging to the nearest tile on tiled games.

And being able to send a message to abort dragging or specify an exact distance to drag can further aid getting the drag right on tiles.

I'm probably going to modify my download of the code myself to add these in, if you accept contributions.

Enabling multitouch breaks onscreen analog controls on HTML5 builds running in iOS Safari

The analog control in the onscreen demo doesn't work when multitouch is enabled. Disabling it by creating a new input binding resource with just a Button 1 mouse event called "touch" and nothing else will cause the analog control to start working again like intended. But this means multitouch can't be used.

I've tested the onscreen demo with multitouch enabled on macOS Chrome, macOS Safari, and Android Chrome, which all work fine. It's only iOS browsers that seem to have this issue. Other multitouch enabled demos also work fine on iOS, like the "gesture" demo.

cursor.OVER reporting game object under (lower z) the tompost game object

The cursor.OVER message is reporting game objects stacked below the topmost game object.

When moving the cursor up on the screen over stacked game objects it is issuing cursor.OUT messages for the topmost game object followed by cursor.OVER messages for the underlying game object. It does this for all the objects in the stack as can be seen in the attached video.

When moving the cursor down on the screen I see what I would call expected behavior. it doesn't issue cursor.OUT / cursor.OVER messages until the cursor has moved over the object and seems to ignore game objects lower in the stack.

cursor.OVER.mp4

If you need additional information or would like me to try something, please let me know.

cursor.script doesn't really send messages to game objects.

Hi,

I found an issue with the cursor script. It didn't seem to send any messages to my game objects. I think the problem is here:
local function notify_event(self, game_object_id, game_object_group, action, message_id)
-- pcall to check if the game object exists since it might have been deleted
-- typically a cursor_out message that is generated when the game object is deleted
local exists,_ = pcall(function()
go.get_id(game_object_id)
end)
Your error catching doesn't function, because go.get_id expects a URL and game_object_id is a hash. It always throws an error, and not because the game object doesn't exists.
I changed the function in go.get_position(game_object_id) because that function does expect a hash and then it seems to work.

I'm new to GitHub, so have patience with me. I haven't figured out pull requests yet.

best,
Theo Ybema

Defect in multitouch handling on iOS devices

There seems to be a new problem with multitouch handling of input events when using the onscreen controls. Virtual stick movement and button touches do not seem to be handled in parallel anymore with the latest version, as can be seen in the onscreen example:

On iOS devices (tested on an iPhone 14, iOS version 16.7 20H19), with the current version input library 4.6.1. master branch, the spaceship can either move or shoot - but not both at the same time. I checked the older version 4.5.1. and with that version, the behavior is still as expected, movement and shooting works in parallel.

Drag events after canceling drag

Okay, it's hard to debug this because breakpoints interrupt the issue, but I think it looks like new drag events are getting generated on the same mousedown. I suppose there could be a use case for this, but for my purposes I'm having trouble thinking of a way to differentiate between the first drag and these later phantom drags. Is there any way to tell it to only allow one drag event per mousedown?

The cursor_out message is not sent to game objects

Hello.
There is a problem with the cursor script.
The cursor_out message is not sent to the game object if you hold down the mouse button and move the cursor out of the game object.
You can see it in the official example when you disable the drag option.
I attach gif.

ezgif-6-5b80f545c55e

Request: Example of a "dropzone" for detecting whether a game object is over a set of coordinates

Hi there,

I'd like to request an example of a dropzone that would detect whether a game object (e.g. playing card) is over a particular area while being dragged with the cursor.

Presumably, the dropzone and game object(s) would use colliders to determine when the game object is over the dropzone. Ideally, there would be a simple API that could return info about the state of the drag event, like isOverDropZone = true, wasDropped = false, etc. This would allow for things like returning the game object to its starting coordinates if it wasn't placed over a dropzone, or disabling its draggable functionality if it was placed correctly.

Thank you!

Cursor registering click at multiple places

Hello,

I am having an issue where the cursor seems to be registering a click on multiple entities at the same time while the cursor is hovered only on top of another.

This happens more often when there are many sprites on the screen. A certain case: 1. the sprite I click on is in the middle of the screen; 2. the click is registered on that sprite and another sprite at the edge of the screen.

This usually seems to happen in a way that the faulty register happens at the edge of the screens.

What can I do about this?

If you delete the object being moved, then we get the error

If you delete (go.delete()) the object being moved, you get an error:

INFO:DLIB: SSDP: Started on address 192.168.100.59
ERROR:SCRIPT: /in/cursor.script:185: Instance (null) not found
stack traceback:
	[C]: in function 'get_position'
	/in/cursor.script:185: in function </in/cursor.script:93>

Is it possible to make protection that does not create an error and bypass such cases?

Thx!

Trying to unregister a node gives an error

registered_node[node] = nil

Should be registered_nodes[node] = nil


ERROR:SCRIPT: /utils/button.lua:73: attempt to index global 'registered_node' (a nil value)
stack traceback:
	/utils/button.lua:73: in function 'unregister'
	/main/screens/idle/idle.gui_script:72: in function </main/screens/idle/idle.gui_script:71>
"""

Cursor demo works partitially

Platform Windows 11 and HTML5
Defold version 1.4.0

Curson demo works partitially:
1 not all blue aliens clicked
2 green aliens not a dragable.

Request: Cursor teleports to mouse position when clicking anywhere (super important for mobile games)

https://forum.defold.com/t/rendercam-defold-input-weird-cursor-position-when-scrolling/69387/7
"This is something the cursor script should support. Please create a ticket in GitHub!" (Britzl)

This feature completion is definitely something anyone working on a mobile game would (absolutely) need :) . . .


Is your feature request related to a problem? Please describe (REQUIRED):
Defold Input extension (by Britzl?) => Currently the cursor can't teleport where the user clicks, which is a huge problem for mobile games (since there is no draggable cursor on mobile, we need to move it instantly where the user taps the screen)

When passing the "mouse position" to the cursor from the "if pressed" input, nothing happens.


Describe the solution you'd like (REQUIRED):
It should be possible to pass the "mouse position" message from the "if pressed" input (or any other solution).

So the cursor would instantly teleport to the object and would make the extension useful for mobile game developers.


Additional context (OPTIONAL):
Here is the minimal version of my current project:
https://github.com/Ragetto/20211002_-PUBLIC-_defold_input_cursor

All states in gestures.two_finger are false

Simple repo
gestures_issue.zip

local gesture					= require "in.gesture"


function init(self)
	msg.post(".", "acquire_input_focus")
	gesture.SETTINGS.multi_touch = true
end

function on_input(self, action_id, action)
	local g = gesture.on_input(self, action_id, action)
	if g and action.released then
		pprint(g)
	end
end

Even though two fingers is swiped the output is this, same goes for any other action with two fingers.

 { --[[0xf1d29270]]
01-21 14:16:20.034  3933  3952 D defold  :   swipe_right = false,
01-21 14:16:20.034  3933  3952 D defold  :   swipe_up = false,
01-21 14:16:20.034  3933  3952 D defold  :   two_finger = { --[[0xf1d292a0]]
01-21 14:16:20.034  3933  3952 D defold  :     swipe_up = false,
01-21 14:16:20.034  3933  3952 D defold  :     tap = false,
01-21 14:16:20.034  3933  3952 D defold  :     swipe_right = false,
01-21 14:16:20.034  3933  3952 D defold  :     swipe_down = false,
01-21 14:16:20.034  3933  3952 D defold  :     long_press = false,
01-21 14:16:20.034  3933  3952 D defold  :     swipe_left = false,
01-21 14:16:20.034  3933  3952 D defold  :     double_tap = false
01-21 14:16:20.034  3933  3952 D defold  :   },
01-21 14:16:20.034  3933  3952 D defold  :   swipe_down = true,
01-21 14:16:20.034  3933  3952 D defold  :   swipe_left = false,
01-21 14:16:20.034  3933  3952 D defold  :   swipe = { --[[0xedf45320]]
01-21 14:16:20.034  3933  3952 D defold  :     from = vmath.vector3(218.33331298828, 935.02783203125, 0),
01-21 14:16:20.034  3933  3952 D defold  :     to = vmath.vector3(416.33331298828, 34.604248046875, 0),
01-21 14:16:20.034  3933  3952 D defold  :     time = 0.11771392822266
01-21 14:16:20.034  3933  3952 D defold  :   }
01-21 14:16:20.034  3933  3952 D defold  : }

No description about input_bindings in README

I spent about 1 hour to detect why I can't get the message_id == cursor.CLICKED
The reason was - different game.input_bindings configuration.
In my project I set Mouse trigger -> Button 1: click and it break cursor.CLICKED message with no warnings or any help to detect what error. After changing Mouse trigger -> Button 1: touch - everything works.

I suggest to add some instructions how to configure game.input_bindings, or add some warnings in library core like "You have no touch events in input config file. CLICK events won't wok"

Thank you =)

Double tap is determined as a single tap at the same time

I used defold-input in my project to detect gestures like horizontal and vertical swipes and taps. And I faced this behavior:

  • when I make single tap, it is detected as a single tap
  • when I make double tap, it is detected as a single tap first, then as a double tap

I thought that something wrong in my project and made a new simple test project where is only one script from the example.
And the behavior is the same. Double click make two prints.

Is there something additional checks that I need to do?

Request: Distance from origin on drag

I suppose this is my fault that I didn't realize this earlier, but I'm pretty sure dx and dy only give the distance traveled since the last frame. Would it be possible to get a pair of extra values representing the distance from where the mouse button was first pressed?

For that matter, just knowing where the mousedown first occurred could be useful as well, though I only really need one or the other at the moment (since having one gives you the other via math).

There's a problem with the cursor (drag)

If you click on the object and quickly move it (drag), it will be moved with an offset. As a result, in dynamic game, the player does not have enough objects and drags them accurately, but with offsets(((

Can this be fixed?
Thanks!

This GIF is recorded in your demo.
GIF: https://imgur.com/sj8u2Ap

Can not use gui.clone as buttons

Registering buttons created from nodes overwrite each other. hash_to_hex(gui.get_id(node)) is identical for clones.

local function ensure_node(node_or_node_id)

local function node_to_key(node)
	local url = msg.url()
	return hash_to_hex(url.socket) .. hash_to_hex(url.path) .. hash_to_hex(url.fragment) .. hash_to_hex(gui.get_id(node))
end

function init(self)
	self.clone = gui.get_node("clone")
	for i=1, 10 do 
		local c = gui.clone(self.clone)
		print(node_to_key(c))
	end
end

Can't unregister a button if supplied id is a string

local button = require "in.button"

function init(self)
  button.register("button", function() print("Press") end)
end

function final(self)
  button.unregister("button")
end

function on_input(self, action_id, action)
  button.on_input(action_id, action)
end

This gives me an error, and by debugging it you can see even though it should set the node to nil the lookup doesn't work.

ERROR:SCRIPT: /utils/button.lua:81: Node used in the wrong scene
stack traceback:
	[C]: in function 'is_enabled'
	/utils/button.lua:81: in function 'is_enabled'
	/utils/button.lua:101: in function 'on_input'

However

local button = require "in.button"

function init(self)
  self.button = gui.get_node("button")
  button.register(self.button, function() print("Press") end)
end

function final(self)
  button.unregister(self.button)
end

function on_input(self, action_id, action)
  button.on_input(action_id, action)
end

Gives no error

Multi touch gesture not clears it's state

There is issue in gesture module after last commit.
Two finger gesture state not properly clears.

Problem:

if action.touch then
  if settings.multi_touch then
    if #action.touch == 2 then
      local t1 = action.touch[1]
      local t2 = action.touch[2]
      if current_touch_count < 2 then
        multi_states[t1.id] = create_touch_state()
        multi_states[t2.id] = create_touch_state()
        t1.pressed = true
        t2.pressed = true
      end
      handle_multi_touch(t1, t2) -- gesture state clears here
    end
    current_touch_count = #action.touch
    -- but if we get a multi-touch with one finger, it will not be cleared here
    -- the state will be saved from the previous two-finger gesture
    return gestures  
  end
end

Possible solution:

if action.touch then
  if settings.multi_touch then
    local was_handled = false -- save if multi touch gesture was handled
    if #action.touch == 2 then
      local t1 = action.touch[1]
      local t2 = action.touch[2]
      if current_touch_count < 2 then
        multi_states[t1.id] = create_touch_state()
        multi_states[t2.id] = create_touch_state()
        t1.pressed = true
        t2.pressed = true
      end
      was_handled = true -- gesture was handled
      handle_multi_touch(t1, t2)
    end
    current_touch_count = #action.touch
    if not was_handled then -- if not we manually clear gesture state
      clear_gesture_state()
    end
    return gestures
  end
end

Cursor.listen not working with url strings

Found when using the example code in cursor.md, it does not work as expected. The callback is never called.

From the current cursor.md:

-- not work
cursor.listen("#cursor", cursor.DRAG_START, function(message_id, message)
	-- prevent dragging of blue aliens
	if message.group == hash("blue") then
		return true -- return true to block the event
	end
end)

It does work as expected if we use the full url instead of the url string "#cursor":

-- works
cursor.listen(msg.url("#cursor"), cursor.DRAG_START, function(message_id, message)
	-- prevent dragging of blue aliens
	if message.group == hash("blue") then
		return true -- return true to block the event
	end
end)

The URL is also how it is in the example controller.script

I was going to submit a PR for cursor.md with updated example code, but then I saw that it says cursor.listen() should take either a url or string, so I'm not sure if the doc needs fixed or cursor.lua needs fixed.

iOS onscreen controls: action.x / action.y are always 0 on button release

There seems to be a problem with the onscreen controls: the x/y position of a touch is not reported correctly upon releasing a button. The action/touch event that is propagated looks e.g. like this:

{ 
  id = hash: [button_a],
  x = 0,
  y = 0,
  released = true,
  pressed = false
}

x and y are always 0, no matter where the touch occurred.
To me, it looks like the problem is in onscreen.lua, lines 34 and 35:

local function create_data(control)
		local data = {
			x = control.x or 0,
			y = control.y or 0,
			id = control.id,
			pressed = control.pressed,
			released = control.released,
		}
		return data
	end 

Upon button release, the parameter "control" passed into the function does not contain "x" and "y". Instead it has an object "control.touch_position" with properties "x" and "y", so that this change seems to fix the problem (although I do not know the code well enough to know about possible side effects):

x = control.x or control.touch_position.x or 0,
y = control.y or control.touch_position.y or 0,

Pinch gesture isn't cancelled if interrupted by locking the screen

This is a very unusual edge case, I only found it when trying to reproduce a different bug.

Steps to reproduce:

  1. Run Defold-Input 4.1.4 example on Android
  2. Select Gesture example
  3. Initiate a two-finger pinch gesture
  4. Lock the screen with the physical button on the device
  5. Release both fingers
  6. Resume the sample
  7. Press a single finger on the screen
  8. Observe the pinch ratio displayed

Expected result:
No two finger gesture is detected

Button callback executes three times

The callback to button.register gets executed three times per click release. I'm not sure if there's a phase to the button callback? Such as click, hold, release. But it's not clear to me why this happens.
Reproduction:
In any of your examples with a button, add a static print statement-- such as in savefile.gui_script inside add a print statement after line #9:

button.register("load/button", function() --line #9
    print("load") --added print

Please add a new property for the cursor script

When moving (drag) an object using the cursor, all the coordinates of the object change.
You need to add a property that allows you to move the object without changing the Z coordinate of the object.
I sort my objects by Z. When I move an object with the cursor, I want to raise the object above others by the Z coordinate. Now the cursor script does not give it because of "go.set_position(pos - self.state.pressed_offset, self.state.pressed_id)".

Now I have to write this way:
"local set_pos = pos - self.state.pressed_offset
go.set(self.state.pressed_id, "position.x", set_pos.x)
go.set(self.state.pressed_id, "position.y", set_pos.y)"

Thank you for the great asset!

Cursor following the mouse - Position passed to cursor from update function => conflicts

From Defold forum
https://forum.defold.com/t/rendercam-defold-input-weird-cursor-position-when-scrolling/69387/6


DEFOLD INPUT (cursor)
(+ camera? not sure there is a link)

Real-time following... when not moving the mouse
When passing the "follow position" message from the input function (as recommended by Britzl), the cursor doesn't follow the mouse when this mouse doesn't move (ex: after scrolling and move moving => the mouse keeps its screen position while the cursor follow the camera movement)

What I did do to make the cursor follow the mouse no matter what?
I’ve added the message passing (to the cursor) in the update loop, which makes the cursor follow the mouse as intended... but it seems to have created some sort of “conflicts” with the other cursor’s action_ids...

Recap
When passing the "follow position" message from the update loop, the “release” input is no longer detected after I have clicked the building. I have to move the mouse to "confirm" the release and upgrade the building.


Here is a minimal version of the project here:
https://github.com/Ragetto/20211002_-PUBLIC-_defold_input_cursor

Bindings and gamepads

I noticed the "all.input_binding" matches the Defold builtins, and the "default.gamepads" in builtins has way more profiles than "in.gamepads". Should I be using the builtins in both cases?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.