Jump to content




Mouse and keyboard input simultaneously

computer lua

  • You cannot reply to this topic
12 replies to this topic

#1 nolongerexistant

  • Validating
  • 201 posts
  • LocationNetherlands

Posted 23 June 2013 - 02:48 PM

Is it possible to check for mouse clicks and handle keyboard input at the same time?
Let's say I have this code:
print("Type something")
input = read()

while true do
event = {os.pullEvent()}

if event[1] == "mouse_click" then
  print("Mouse click")
end
end

How would I check for mouse clicks while it's waiting for the user to type something?

#2 Engineer

  • Members
  • 1,378 posts
  • LocationThe Netherlands

Posted 23 June 2013 - 03:02 PM

Of course, the only thing that makes it complex is that you have to write your own read function. This is very, very primitive:
local str = ""

while true do
	local event = { os.pullEvent() }
	if event[1] == "mouse_click" then
		-- Do stuff with your mouse
	elseif event[1] == "char" then
		str = str .. event[2]
	end
end

But like I said, you can take this to the next level and make it super complex if you really want. Only Im not doing that for you :P

#3 Grim Reaper

  • Members
  • 503 posts
  • LocationSeattle, WA

Posted 23 June 2013 - 03:38 PM

Engineer gave a great example of how you might do what you're asking for.

Here's a similar way, but using coroutines:

local function mouseClickHandler (eventName, clickType, xClickPos, yClickPos)
	local currentCursorPos = { term.getCursorPos() }

	term.setCursorPos (1, currentCursorPos[2] + 1)
	term.write ("Mouse click at: (" .. currentCursorPos[1] .. ", " .. currentCursorPos[2] .. ')')
        term.setCursorPos (unpack (currentCursorPos))
end

local function modifiedRead()
	local readCoroutine = coroutine.create (read)
	coroutine.resume (readCoroutine)

	local mouseClickHandlerCoroutine = coroutine.create (mouseClickHandler)

	while coroutine.status (readCoroutine) ~= "dead" do
		local eventData = { os.pullEvent() }

		if eventData[1] == "mouse_click" then
			coroutine.resume (mouseClickHandler, unpack (eventData))
		else
			coroutine.resume (readCoroutine, unpack (eventData))
		end
	end
end


#4 nolongerexistant

  • Validating
  • 201 posts
  • LocationNetherlands

Posted 23 June 2013 - 04:22 PM

View PostEngineer, on 23 June 2013 - 03:02 PM, said:

Of course, the only thing that makes it complex is that you have to write your own read function. This is very, very primitive:

-snip-

But like I said, you can take this to the next level and make it super complex if you really want. Only Im not doing that for you :P

Engineer your example works great, that's the second time tonight :P

View PostGrim Reaper, on 23 June 2013 - 03:38 PM, said:

Engineer gave a great example of how you might do what you're asking for.

Here's a similar way, but using coroutines:

-snip-

Is there an advantage on using coroutines here? All I can think of is that you can actually click and type at the same time

#5 MysticT

    Lua Wizard

  • Members
  • 1,597 posts

Posted 23 June 2013 - 05:47 PM

Why would you write a coroutine manager when you have the parallel api? ;)
local input

local function getInput()
  print("Type something:")
  input = read()
end

local function getMouseInput()
  while true do
    local evt, btn, x, y = os.pullEvent("mouse_click")
    -- Handle the mouse click here
  end
end

parallel.waitForAny(getInput, getMouseInput)


#6 nolongerexistant

  • Validating
  • 201 posts
  • LocationNetherlands

Posted 24 June 2013 - 12:46 PM

View PostMysticT, on 23 June 2013 - 05:47 PM, said:

Why would you write a coroutine manager when you have the parallel api? ;)
-snip-

If I use your method, and I click something that clears the screen, it still waits for an input. Is there way to stop that?

#7 Engineer

  • Members
  • 1,378 posts
  • LocationThe Netherlands

Posted 24 June 2013 - 12:54 PM

View PostSnakybo, on 24 June 2013 - 12:46 PM, said:

If I use your method, and I click something that clears the screen, it still waits for an input. Is there way to stop that?

Then you must have your own read function that checks continueusly if a boolean is true. If that is true it will break that loop it is in

#8 nolongerexistant

  • Validating
  • 201 posts
  • LocationNetherlands

Posted 24 June 2013 - 12:59 PM

View PostEngineer, on 24 June 2013 - 12:54 PM, said:

View PostSnakybo, on 24 June 2013 - 12:46 PM, said:

If I use your method, and I click something that clears the screen, it still waits for an input. Is there way to stop that?

Then you must have your own read function that checks continueusly if a boolean is true. If that is true it will break that loop it is in

That'll work :P

#9 MysticT

    Lua Wizard

  • Members
  • 1,597 posts

Posted 24 June 2013 - 02:03 PM

The parallel.waitForAny call should return when one of the functions ends. So, you just have to make the mouse input function end and it will end the other one too. Example:
local input

local function getInput()
  print("Type something:")
  input = read()
end

local function getMouseInput()
  while true do
    local evt, btn, x, y = os.pullEvent("mouse_click")
    break -- stop the loop when we get a mouse click
  end
end

parallel.waitForAny(getInput, getMouseInput)

term.clear()
term.setCursorPos(1, 1)
if input then
  print("Your input: ", input)
else
  print("You clicked the screen!")
end

If this is not what you need, please explain what you are trying to do, so we can help.

#10 nolongerexistant

  • Validating
  • 201 posts
  • LocationNetherlands

Posted 24 June 2013 - 04:38 PM

View PostMysticT, on 24 June 2013 - 02:03 PM, said:

The parallel.waitForAny call should return when one of the functions ends. So, you just have to make the mouse input function end and it will end the other one too. Example:
-snip-

If this is not what you need, please explain what you are trying to do, so we can help.

Your method combined with a custom read function and os.queueEvent() worked mostly fine, just when I clicked something, it executed the command from the click before it ended the keyboard input loop, causing buttons on the next screen to not-respond for some reason. I guess becouse there were multiple os.pullEvent()'s running

But i've just found that this method works perfect:
Spoiler

It's pretty much the same as your function but i've used return instead of break since the wiki states "stops when any of them returns."

#11 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 24 June 2013 - 11:44 PM

your code will error after you restart your computer. Move your functions above the parallel call to fix this future problem.

#12 nolongerexistant

  • Validating
  • 201 posts
  • LocationNetherlands

Posted 25 June 2013 - 04:10 AM

View Posttheoriginalbit, on 24 June 2013 - 11:44 PM, said:

your code will error after you restart your computer. Move your functions above the parallel call to fix this future problem.

Thanks TOB

#13 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 25 June 2013 - 08:44 AM

View PostSnakybo, on 25 June 2013 - 04:10 AM, said:

Thanks TOB
No problems :) as always here to help...

Also, just a side note, if you want to shorten either BIT or TOBIT. I'd prefer former over latter. :)





2 user(s) are reading this topic

0 members, 2 guests, 0 anonymous users