Can't detect click on game objects using cursor script with orthographic camera (SOLVED)

Hi,

I’m using the cursor script together with the orthographic camera, and I’m having some issues.

I can’t get game objects to receive the messages from the cursor. The cursor itself gets the messages perfectly when clicking on objects with a collider though. I got that working after making my own copy of cursor.script and adjusting the handle_input() function to use camera.screen_to_world() on the action position. Are there any other adjustments I need to be doing to get these two plugins to work together? I’m using FIXED_ZOOM projection with a zoom of 4 on the camera.

This is my game object script where I’m listening to messages, which don’t seem to be run at all:

local cursor = require "in.cursor"

function on_message(self, message_id, message, sender)
	pprint(message)
	if message_id == cursor.OVER then
		print("over pickup")
	elseif message_id == cursor.OUT then
		print("out pickup")
	elseif message_id == cursor.PRESSED or message_id == cursor.RELEASED then
		print("pressed pickup")
	end
end

And this is my cursor controller script, which actually receives messages:

local cursor = require "in.cursor"

function init(self)
	if not go.get("#cursor", "acquire_input_focus") then
		self.forward_input = true
		msg.post(".", "acquire_input_focus")
	end
end

function on_input(self, action_id, action)
	if self.forward_input then
		msg.post("#cursor", "input", { action_id = action_id, action = action })
	end
end

function on_message(self, message_id, message, sender)
	if message_id == cursor.OVER then
		print("Cursor over", message.id, message.group, message.x, message.y)
	elseif message_id == cursor.OUT then
		print("Cursor out", message.id, message.group, message.x, message.y)
	elseif message_id == cursor.PRESSED then
		print("Pressed", message.id, message.group, message.x, message.y)
	elseif message_id == cursor.RELEASED then
		print("Released", message.id, message.group, message.x, message.y)
	elseif message_id == cursor.DRAG_START then
		print("Drag started", message.id, message.group, message.x, message.y)
	elseif message_id == cursor.DRAG_END then
		print("Drag ended", message.id, message.group, message.x, message.y)
	end
end

Tell me if you want some more information. Thanks! :slight_smile:

Check the section on input handling for the cursor script:

You need to use the second option.

2 Likes

Ah, yes I saw that section but I didn’t really understand it. Sorry, I should have asked that as well. What does it mean to “pass input messages” instead, and how is this done? Does it mean just setting up an on_input() function in the game object and doing actions there? Thank you for such a quick response!

It means that you should from some script acquire input focus, translate it using screen to world, then send a message containing translated data to the cursor script.

Like this: https://github.com/britzl/defold-input/blob/4f1e5a9624d9b5d9f8da33670a085910fbc6c742/examples/cursor/controller.script#L12

2 Likes

Thank you! So just like the controller in the example, but updating the action position with the camera module? This is what I’m doing now:

function on_input(self, action_id, action)
	if self.forward_input and action_id ~= nil then
		local translatedPos = camera.screen_to_world(cameraId, vmath.vector3(action.x, action.y, 0));
		action.x = translatedPos.x
		action.y = translatedPos.y
		msg.post("#cursor", "input", { action_id = action_id, action = action })
	end
end

And then in the same script I listen to that message:

function on_message(self, message_id, message, sender)
	if message_id == cursor.OVER then
		print("Cursor over", message.id, message.group, message.x, message.y)
	elseif message_id == cursor.OUT then
		print("Cursor out", message.id, message.group, message.x, message.y)
	elseif message_id == cursor.PRESSED then
		print("Pressed", message.id, message.group, message.x, message.y)
	elseif message_id == cursor.RELEASED then
		print("Released", message.id, message.group, message.x, message.y)
	elseif message_id == cursor.DRAG_START then
		print("Drag started", message.id, message.group, message.x, message.y)
	elseif message_id == cursor.DRAG_END then
		print("Drag ended", message.id, message.group, message.x, message.y)
	end
end

Am I on the right track? Judging by the output that I get, the pressed and released inputs behave as expected, but the over only gets fired when clicking. I assume that’s because it’s not considered an “input action” on its own?

Lastly, if I want to pass this message on to the game object that was clicked, that’s already handled by the cursor.script right? Or would I use msg.post() to post to them inside the above on_message() function?

1 Like

Yes I believe so. Looks good to me.

Exactly, that should already be done by the script.

1 Like

I’ve got it working now. The clicks are properly registered, and I learned a lot about message passing. I’m trying to make a simple point and click game. This is my first time getting into Defold, and Lua for that matter, and I’m liking it a lot. Thank you so much for all the help! Invaluable.

3 Likes