This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
minecraftwarlock's profile picture

Monitor Click Sensing Function Not Working

Started by minecraftwarlock, 04 September 2014 - 05:27 AM
minecraftwarlock #1
Posted 04 September 2014 - 07:27 AM
I have been trying to create a advanced monitor button clicking API, but I have been having problems with one of the functions. The function is supposed to wait for a click then return which button is clicked if a button is clicked, otherwise it keeps going until a button is clicked.

This is the API:

--wrap the monitor as a peripheral
mon = peripheral.wrap("left")

mainBackground = colors.black
mainText = colors.white

--table that stores the buttons
buttons = {}

--define a new button
function newButton(lbl,txt,x,y,text,bg,border)--newButton(string,string,integer,integer,colors api,colors api,boolean)
	buttons[lbl] = {txt,x,y,false,lbl,text,bg,border}
end

--draw a button
function drawButton(button)
	buttons[button][4] = true
	mon.setBackgroundColor(buttons[button][7])
	mon.setTextColor(buttons[button][6])
	mon.setCursorPos(buttons[button][2],buttons[button][3] + 1)
	mon.write(" "..buttons[button][1].." ")

	if buttons[button][8] then
		mon.setCursorPos(buttons[button][2],buttons[button][3])

		for i=1,string.len(buttons[button][1]) + 2 do
			mon.write(" ")
		end

		mon.setCursorPos(buttons[button][2],buttons[button][3] + 2)

		for i=1,string.len(buttons[button][1]) + 2 do
			mon.write(" ")
		end
	end
end

--erase a button
function eraseButton(button)
	buttons[button][4] = false
	mon.setBackgroundColor(mainBackground)
	mon.setTextColor(mainText)

	mon.setCursorPos(buttons[button][2],buttons[button][3] + 1)

	for i=1,string.len(buttons[button][1]) + 2 do
		mon.write(" ")
	end

	if buttons[button][8] then
		mon.setCursorPos(buttons[button][2],buttons[button][3] + 2)

		for i=1,string.len(buttons[button][1]) + 2 do
			mon.write(" ")
		end

		mon.setCursorPos(buttons[button][2],buttons[button][3])

		for i=1,string.len(buttons[button][1]) + 2 do
			mon.write(" ")
		end
	end
end

--clear the monitor and erase all buttons
function monDefault()
	mon.setBackgroundColor(mainBackground)
	mon.setTextColor(mainText)

	for button in pairs(buttons) do
		eraseButton(button)
	end

	mon.clear()
	mon.setCursorPos(1,1)
end

--the problematic function
function getClick()
	while true do
		event,side,xPos,yPos = os.pullEvent("monitor_touch")
		for button in pairs(buttons) do
			if buttons[button][8] then
				if xPos >= buttons[button][2] and xPos <= buttons[button][2] + string.len(buttons[button][1]) + 1 and yPos >= buttons[button][3] and yPos <= buttons[button][3] + 2 and buttons[button][4] then
					return buttons[button][5]
				elseif xPos >= buttons[button][2] and xPos <= buttons[button][2] + string.len(buttons[button][1]) - 1 and yPos == buttons[button][3] and buttons[button][4] then
					return buttons[button][5]
				end
			end
		end
	end
end

This is the sample code that calls the API:

button.newButton("test","test",5,5,colors.red,colors.white,true)
button.drawButton("test")
print(button.getClick())
Lyqyd #2
Posted 04 September 2014 - 07:31 AM
What does it do instead of doing what you expect?
minecraftwarlock #3
Posted 04 September 2014 - 07:35 AM
It always reutrns nil.
DannySMc #4
Posted 08 September 2014 - 12:13 PM
It always reutrns nil.

When you make a button, make it output a file? So save the table to a file, then read the file over and make sure everything you want is saved in the right place, also make sure all the table calls are valid. It's a random shot but I can't see a problem, but make sure the table is actually valid first.

Try:

local file = fs.open("output.lua", "w")
file.write(textutils.serialize(YOUR_TABLE)
file.close()

Then just open the file in a Lua editor ( I used Notepad ++ or Netbeans 8.0)
Otherwise go on a server and I can see if I can help?
Bomb Bloke #5
Posted 08 September 2014 - 02:23 PM
The only thing I can think of is that you might be forgetting to load the API before you attempt to use it?:

os.loadAPI("button")
minecraftwarlock #6
Posted 09 September 2014 - 06:22 AM
The only thing I can think of is that you might be forgetting to load the API before you attempt to use it?:

os.loadAPI("button")

I'm loading the API on startup
Bomb Bloke #7
Posted 09 September 2014 - 06:38 AM
In that case, I don't know what to tell you. I've tested out your code and it works fine. Make sure the code here is the code you're actually running, and if you're still stuck, pastebin the full code and post a screenshot of what it does.
minecraftwarlock #8
Posted 09 September 2014 - 06:42 AM
I've just done more extensive testing it turns out it is returning an empty string not nil
minecraftwarlock #9
Posted 09 September 2014 - 07:03 AM
I got it to return something, but it still returns an empty string when I click nothing. What I'm trying to get it to do is get it not to return until something has been clicked.
Bomb Bloke #10
Posted 09 September 2014 - 10:09 AM
The way your function is written means that it can only return if it decides a button was clicked. It would then return the name of that button. Again, I suspect the code you're showing here is not the same as the code that's causing you issues.

Looking a bit closer, I do see your usage of buttons[button][8] is a bit odd. You're want that to determine whether the button is one or three lines high, yes? Change the logic around a bit like this:

--the problematic function
function getClick()
	while true do
		local event,side,xPos,yPos = os.pullEvent("monitor_touch")
		for button in pairs(buttons) do
			if buttons[button][8] and xPos >= buttons[button][2] and xPos <= buttons[button][2] + string.len(buttons[button][1]) + 1 and yPos >= buttons[button][3] and yPos <= buttons[button][3] + 2 and buttons[button][4] then
				return button
			elseif (not buttons[button][8]) and xPos >= buttons[button][2] and xPos <= buttons[button][2] + string.len(buttons[button][1]) - 1 and yPos == buttons[button][3] and buttons[button][4] then
				return button
			end
		end
	end
end
minecraftwarlock #11
Posted 10 September 2014 - 06:42 AM
The way your function is written means that it can only return if it decides a button was clicked.

That's what it's supposed to do but it returns an empty string when nothing is clicked.

By the way I updated the function to the one you posted.
Bomb Bloke #12
Posted 10 September 2014 - 12:20 PM
The new version of the function was aimed at a different issue. As stated, I can't replicate the problem you're talking about. Make certain the API you're loading is the API you're showing here. Stick random print statements in it and see if they execute, for example. Failing that, throw up pastebin links for the current version of the API you're using plus the code you're calling it from, as well as screenshots of the problematic output.
minecraftwarlock #13
Posted 15 September 2014 - 08:00 AM
I found the problem, I was using notepad++ to edit the code and it was saving to the wrong location so an old version of the API was being loaded.
minecraftwarlock #14
Posted 16 September 2014 - 08:42 AM
I have updated the code to have error messages and given the getClick function an optional timeout.
This is the pastebin for the API
http://pastebin.com/fuFAH9kZ
Here is an example script
http://pastebin.com/Ne5qT0gj