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

Writing Out Multiple Tables

Started by GamerNebulae, 28 July 2013 - 12:42 PM
GamerNebulae #1
Posted 28 July 2013 - 02:42 PM
Dear CC gods,

I am working on a monitor API. Sorta like the one DireWolf20 made. I looked at his, but I find his way of coding very fuzzy and non-logical. Do you guys have any idea? This is what the table looks like:

buttonTable[name]["xMin"] = xMin

I hope you guys can help me

Yours sincerely,

GamerNebulae
LBPHacker #2
Posted 28 July 2013 - 03:28 PM
buttonTable is a two-dimensional table. buttonTable[name] is another table which has the index "xMin".
TheOddByte #3
Posted 28 July 2013 - 03:59 PM
Do you mean something like this? .-.

buttonTable[name].xMin = xMin

An example

tNames = {
[1] = {
name = "Hellkid98(me)",
age = 15,
},

[2] = {
name = "Someone",
age = "Unknown",
},
}

for i = 1,#tNames do
print(tNames[i].name.."  Age: "..tNames[i].age)
end

In your case when you use a name index for table

tPersons = {
["Ryan"] = {
name = "Ryan",
age = 17,
},

["Harold"] = {
name = "Harold"
age = 45,
},
}

print(tPersons["Ryan"].name.."  Age: "..tPersons["Ryan"].age)
GamerNebulae #4
Posted 28 July 2013 - 05:38 PM
Do you mean something like this? .-.

buttonTable[name].xMin = xMin

An example

tNames = {
[1] = {
name = "Hellkid98(me)",
age = 15,
},

[2] = {
name = "Someone",
age = "Unknown",
},
}

for i = 1,#tNames do
print(tNames[i].name.."  Age: "..tNames[i].age)
end

In your case when you use a name index for table

tPersons = {
["Ryan"] = {
name = "Ryan",
age = 17,
},

["Harold"] = {
name = "Harold"
age = 45,
},
}

print(tPersons["Ryan"].name.."  Age: "..tPersons["Ryan"].age)

Dear hellkid,

The problem is, is that it is a multi-dimensional array. I don't know how many buttons people will have on the monitor. That makes it so tricky.
LBPHacker #5
Posted 28 July 2013 - 05:42 PM
Iterate through the table then:
for key, value in paris(buttonTable) do
    print(textutils.unserialize(value))
end
TheOddByte #6
Posted 29 July 2013 - 07:39 AM
Then I'm guessing you have a function to create buttons?

buttons = {}

function createButton(sX,fX,y)
nButton = {}
nButton.sX = sX
nButton.fX = fX
nButton.y = y

table.insert(buttons,nButton)
end

You should show us the full code you have
GamerNebulae #7
Posted 29 July 2013 - 08:27 AM
I got the code here for you guys. Can't really use much bandwith at the moment:


function buttonTableTable(name, xMin, xMax, yMin, yMax, text)
buttonTable[name]["active"] = false
buttonTable[name]["xMin"] = xMin
buttonTable[name]["xMax"] = xMax
buttonTable[name]["yMin"] = yMin
buttonTable[name]["yMax"] = yMax
buttonTable[name]["text"] = text
x,y = mon.getScreenSize()
if (xMin or xMax) > x then
  print(fault.outOfBounds)
elseif (xMin or xMax) < x then
  print(fault.outOfBounds)
elseif (yMin or yMax) > y then
  print(fault.outOfBounds)
elseif (yMin or yMax) < y then
  print(fault.outOfBounds)
else
  xText = math.floor((((buttonTable[name]["xMin"] + buttonTable[name]["xMax"])-string.len(buttonTable[name]["text"]))/2)+1)
  yText = math.floor((buttonTable[name]["yMin"] + buttonTable[name]["yMax"])/2)
  mon.setBackgroundColor(16384)
  for i = yMin, yMax do
   for j = xMin, xMax do
    if (i == yText and j == xText) then
	 mon.write(buttonTable[name]["text"])
    else
	 mon.write(" ")
    end
   end
  end
end
end
GamerNebulae #8
Posted 30 July 2013 - 10:45 AM
Then I'm guessing you have a function to create buttons?

buttons = {}

function createButton(sX,fX,y)
nButton = {}
nButton.sX = sX
nButton.fX = fX
nButton.y = y

table.insert(buttons,nButton)
end

You should show us the full code you have

I posted the code. Maybe you can help me now.
TheOddByte #9
Posted 30 July 2013 - 01:00 PM
Don't know if this works since I haven't tested it but..
Spoiler

function buttonTableTable(name, xMin, xMax, yMin, yMax, text)
buttonTable[name].active = false
buttonTable[name].xMin = xMin
buttonTable[name].xMax = xMax
buttonTable[name].yMin = yMin
buttonTable[name].yMax = yMax
buttonTable[name].text = text
x,y = mon.getScreenSize()
if (xMin or xMax) > x then
  print(fault.outOfBounds)
elseif (xMin or xMax) < x then
  print(fault.outOfBounds)
elseif (yMin or yMax) > y then
  print(fault.outOfBounds)
elseif (yMin or yMax) < y then
  print(fault.outOfBounds)
else
  xText = math.floor((((buttonTable[name].xMin + buttonTable[name].xMax)-string.len(buttonTable[name].text))/2)+1)
  yText = math.floor((buttonTable[name]yMin + buttonTable[name].yMax)/2)
  mon.setBackgroundColor(16384)
  for i = yMin, yMax do
   for j = xMin, xMax do
    if (i == yText and j == xText) then
     mon.write(buttonTable[name].text)
    else
     mon.write(" ")
    end
   end
  end
end
end

Just so you know

tNumbers = {
["One"] = {
num = 1,
},

["Two"] = {
num = 2,
["addTwo"] = { num = 2 + 2,},
},
}

--[[
When you are trying to print(buttonTable[name]["xMin"])
You are trying to print the table inside the table with the name
And the table would kinda look like this

buttonTable = {
["SomeName"] = {
["xMin"] = { 12,}
},
}

But you are meaning todo this
buttonTable = {
["SomeName"] = {
xMin = 12,
xMax = 20,
text = "Hello",
},
}

print(buttonTable["SomeName"].text)
-- This would print Hello

]]--

If you still don't know how to use tables then check out the lua page about tables..
GamerNebulae #10
Posted 30 July 2013 - 01:24 PM
Dear ComputerCraft pro's,

I am working on a monitor API. Sorta like the one DireWolf20 made. The difference is is that it is a direct setup where you only have to type one line and it works. An API for beginners you could say. It has a button function, heading, etc. The problem is is getting the button arrays on the screen. They are multi-dimensional. Which means you can have multiple buttons at once. Here is the code:


function buttonTableTable(name, xMin, xMax, yMin, yMax, text)
buttonTable[name]["active"] = false
buttonTable[name]["xMin"] = xMin
buttonTable[name]["xMax"] = xMax
buttonTable[name]["yMin"] = yMin
buttonTable[name]["yMax"] = yMax
buttonTable[name]["text"] = text
x,y = mon.getScreenSize()
if (xMin or xMax) > x then
  print(fault.outOfBounds)
elseif (xMin or xMax) < x then
  print(fault.outOfBounds)
elseif (yMin or yMax) > y then
  print(fault.outOfBounds)
elseif (yMin or yMax) < y then
  print(fault.outOfBounds)
else
  xText = math.floor((((buttonTable[name]["xMin"] + buttonTable[name]["xMax"])-string.len(buttonTable[name]["text"]))/2)+1)
  yText = math.floor((buttonTable[name]["yMin"] + buttonTable[name]["yMax"])/2)
  mon.setBackgroundColor(16384)
  for i = yMin, yMax do
   for j = xMin, xMax do
    if (i == yText and j == xText) then
	 mon.write(buttonTable[name]["text"])
    else
	 mon.write(" ")
    end
   end
  end
end
end

I hope you guys can help me.
Bubba #11
Posted 30 July 2013 - 01:47 PM
What exactly is your question? I mean I know that you say the problem is getting the button array on the screen, but are you asking for help going through each button and drawing it on the screen or are you actually encountering errors?
GamerNebulae #12
Posted 30 July 2013 - 01:54 PM
What exactly is your question? I mean I know that you say the problem is getting the button array on the screen, but are you asking for help going through each button and drawing it on the screen or are you actually encountering errors?

My problem is, that whenever there are multiple buttons, I have no clue how to draw them all. I know how to draw one, but not multiple ones.
Bubba #13
Posted 30 July 2013 - 01:58 PM
My problem is, that whenever there are multiple buttons, I have no clue how to draw them all. I know how to draw one, but not multiple ones.

Well you're actually pretty close already. All you need is a function to draw each button individually and then loop over the table that stores your buttons. For example:


local buttonTable = {}

local function addButton(...)
  table.insert(buttonTable, {...}) --#You may want to consider doing it this way. It makes things considerably easier :)/>/>
end

local function drawButton(btn)
  --#You know how to handle drawing an individual button
  term.setCursorPos(btn[1],btn[2]) --#Sure, not quite as readable my way, but it is quite a bit shorter and you don't have to mess around with inserting names into the button table
  term.write(btn[3])
end

local function drawAllButtons()
  for buttonIndex, btn in pairs(buttonTable) do --#Just iterate over every button and draw it with the drawButton function
    drawButton(btn)
  end
end

Is this what you're looking for?
Lyqyd #14
Posted 30 July 2013 - 02:03 PM
Threads merged. Use only one topic for all questions about the same piece of code, even if you seem to feel that we aren't helping you fast enough for your liking.
GamerNebulae #15
Posted 30 July 2013 - 02:34 PM
My problem is, that whenever there are multiple buttons, I have no clue how to draw them all. I know how to draw one, but not multiple ones.

Well you're actually pretty close already. All you need is a function to draw each button individually and then loop over the table that stores your buttons. For example:


local buttonTable = {}

local function addButton(...)
  table.insert(buttonTable, {...}) --#You may want to consider doing it this way. It makes things considerably easier :)/>/>/>
end

local function drawButton(btn)
  --#You know how to handle drawing an individual button
  term.setCursorPos(btn[1],btn[2]) --#Sure, not quite as readable my way, but it is quite a bit shorter and you don't have to mess around with inserting names into the button table
  term.write(btn[3])
end

local function drawAllButtons()
  for buttonIndex, btn in pairs(buttonTable) do --#Just iterate over every button and draw it with the drawButton function
	drawButton(btn)
  end
end

Is this what you're looking for?

Can you maybe plug into the code I have now? It feels quite alien for me. I would like to keep it the way it is now, because as I said: I want to keep it a simple API for every CC-user to use.
Bubba #16
Posted 30 July 2013 - 02:38 PM
Can you maybe plug into the code I have now? It feels quite alien for me. I would like to keep it the way it is now, because as I said: I want to keep it a simple API for every CC-user to use.

The use of the API would not change one bit. Just the way that it is written.

Is there some part that you do not understand about it? I don't want to do the work of plugging it in if you have not tried to do so yourself.
GamerNebulae #17
Posted 30 July 2013 - 02:41 PM
The way how you iterate through the tables is the part where I get confused. For the rest I understand almost everything.
Bubba #18
Posted 30 July 2013 - 02:57 PM
The way how you iterate through the tables is the part where I get confused. For the rest I understand almost everything.

You mean a for x,y in pairs loop? Here is a link to Programming in Lua which might help you out with that.

Basically though, a pairs loop just goes through every single item in a table and assigns the index of the item to the first argument and the value of the item to the second. So for example:

some_table = {
  [1] = "Hello!",
  [2] = "Goodbye!"
}

for index, value in pairs(some_table) do
  print(index..": "..value)
end

The above code could output:
1: Hello
2: Goodbye
or
2: Goodbye
1: Hello

Due to the fact that pairs does not go in any specific order but rather gets the indexes at "random".
GamerNebulae #19
Posted 30 July 2013 - 03:25 PM
The way how you iterate through the tables is the part where I get confused. For the rest I understand almost everything.

You mean a for x,y in pairs loop? Here is a link to Programming in Lua which might help you out with that.

Basically though, a pairs loop just goes through every single item in a table and assigns the index of the item to the first argument and the value of the item to the second. So for example:

some_table = {
  [1] = "Hello!",
  [2] = "Goodbye!"
}

for index, value in pairs(some_table) do
  print(index..": "..value)
end

The above code could output:
1: Hello
2: Goodbye
or
2: Goodbye
1: Hello

Due to the fact that pairs does not go in any specific order but rather gets the indexes at "random".

So if I do this:


for name, iterations in pairs(buttonTable) do
	for y = buttonTable[name]["yMin"], buttonTable[name]["yMax"] do
		for x = buttonTable[name]["xMin"], buttonTable[name]["xMax"] do
			etc...
		end
	end
end
TheOddByte #20
Posted 30 July 2013 - 04:34 PM
The way how you iterate through the tables is the part where I get confused. For the rest I understand almost everything.

You mean a for x,y in pairs loop? Here is a link to Programming in Lua which might help you out with that.

Basically though, a pairs loop just goes through every single item in a table and assigns the index of the item to the first argument and the value of the item to the second. So for example:

some_table = {
  [1] = "Hello!",
  [2] = "Goodbye!"
}

for index, value in pairs(some_table) do
  print(index..": "..value)
end

The above code could output:
1: Hello
2: Goodbye
or
2: Goodbye
1: Hello

Due to the fact that pairs does not go in any specific order but rather gets the indexes at "random".
Wouldn't ipairs go in order? .-.
GamerNebulae #21
Posted 30 July 2013 - 04:48 PM
The way how you iterate through the tables is the part where I get confused. For the rest I understand almost everything.

You mean a for x,y in pairs loop? Here is a link to Programming in Lua which might help you out with that.

Basically though, a pairs loop just goes through every single item in a table and assigns the index of the item to the first argument and the value of the item to the second. So for example:

some_table = {
  [1] = "Hello!",
  [2] = "Goodbye!"
}

for index, value in pairs(some_table) do
  print(index..": "..value)
end

The above code could output:
1: Hello
2: Goodbye
or
2: Goodbye
1: Hello

Due to the fact that pairs does not go in any specific order but rather gets the indexes at "random".
Wouldn't ipairs go in order? .-.

The question is: "Will it blend?" My real question is is of my code will work.
LBPHacker #22
Posted 30 July 2013 - 04:52 PM
Wouldn't ipairs go in order? .-.
It would. But it would iterate through the numeric indices only.
GamerNebulae #23
Posted 30 July 2013 - 06:04 PM
Wouldn't ipairs go in order? .-.
It would. But it would iterate through the numeric indices only.

Nothing that would be any use for me though..
theoriginalbit #24
Posted 30 July 2013 - 06:29 PM
The thing to remember is that ipairs will only iterate sequential numerical indexes and it will be in order. However pairs will not have any order for the key/value pairs, but numerical indexes are iterated first AND in order!

Example:

Assume we have this table

local t = {
  "this",
  key = "value",
  ["some key"] = "some value",
  "that",
  [5] = "the other",
}

ipairs loop

for i,v in ipairs(t) do
  print( i.." : "..v )
end

will output
1 : this
2 : that

pairs loop

for k,v in pairs(t) do
  print( k.." : "..v )
end

will output
1 : this
2 : that
5 : the other
some key : some value
key : value

NOTE: the key/value pairs may be in a different order, i didn't actually run this code, it should be noted that it can be in any order (not alphabetical or adding order) but each time you iterate it will be in the same order as previous times.
GamerNebulae #25
Posted 31 July 2013 - 05:23 AM
The thing to remember is that ipairs will only iterate sequential numerical indexes and it will be in order. However pairs will not have any order for the key/value pairs, but numerical indexes are iterated first AND in order!

Example:

Assume we have this table

local t = {
  "this",
  key = "value",
  ["some key"] = "some value",
  "that",
  [5] = "the other",
}

ipairs loop

for i,v in ipairs(t) do
  print( i.." : "..v )
end

will output
1 : this
2 : that

pairs loop

for k,v in pairs(t) do
  print( k.." : "..v )
end

will output
1 : this
2 : that
5 : the other
some key : some value
key : value

NOTE: the key/value pairs may be in a different order, i didn't actually run this code, it should be noted that it can be in any order (not alphabetical or adding order) but each time you iterate it will be in the same order as previous times.

The problem isn't with the pairs or ipairs. It doesn't matter what order they go in. The problem is cycling through the first element in the array. If you look at the code you will see three things:
1: The table name
2: The name of the button (first element in the table)
3: The values (second element in the table)
LBPHacker #26
Posted 31 July 2013 - 05:36 AM
the first element in the array
The first dimension, you mean? Still use pairs:
for key, value in pairs(buttonTable) do
    -- key is a string: contains the name of the button
    -- value is a table: contains the information accosiated with the button
end
GamerNebulae #27
Posted 31 July 2013 - 05:39 AM
the first element in the array
The first dimension, you mean? Still use pairs:
for key, value in pairs(buttonTable) do
	-- key is a string: contains the name of the button
	-- value is a table: contains the information accosiated with the button
end

If I grab my code from earlier on and redesign it a bit, should it work?


for name, value in pairs(buttonTable) do
	    for y = buttonTable[name]["yMin"], buttonTable[name]["yMax"] do
			    for x = buttonTable[name]["xMin"], buttonTable[name]["xMax"] do
					    etc...
			    end
	    end
end
LBPHacker #28
Posted 31 July 2013 - 05:59 AM
If I grab my code from earlier on and redesign it a bit, should it work?
Sure it should. Although since value essentially contains buttonTable[name], you could replace every occurence of buttonTable[name] with value.
GamerNebulae #29
Posted 31 July 2013 - 06:22 AM
If I grab my code from earlier on and redesign it a bit, should it work?
Sure it should. Although since value essentially contains buttonTable[name], you could replace every occurence of buttonTable[name] with value.

So if I turn those two around, they will be right?

for value, name in pairs(buttonTable) do
end
LBPHacker #30
Posted 31 July 2013 - 06:24 AM
Nope. The loop is fine as it is. Just replace "buttonTable[name]" with "value" INSIDE the loop, because they hold the same table. But leave the "name, value" part as it is. Even if you don't use "name", it has to be there.
GamerNebulae #31
Posted 31 July 2013 - 06:41 AM
Nope. The loop is fine as it is. Just replace "buttonTable[name]" with "value" INSIDE the loop, because they hold the same table. But leave the "name, value" part as it is. Even if you don't use "name", it has to be there.

Can you give an example how it would work in my code?
theoriginalbit #32
Posted 31 July 2013 - 06:56 AM
Can you give an example how it would work in my code?


for name, value in pairs(buttonTable) do
  for y = value["yMin"], value["yMax"] do
	for x = value["xMin"], value["xMax"] do
	  etc...
	end
  end
end

EDIT: haha! I'm a ninja! :ph34r:/>
Edited on 31 July 2013 - 04:57 AM
LBPHacker #33
Posted 31 July 2013 - 06:56 AM
EDIT: HOLY CRAP Bit that was fast! (been ninja'd)

Well, this is your code, right?
for name, value in pairs(buttonTable) do
    for y = buttonTable[name]["yMin"], buttonTable[name]["yMax"] do
        for x = buttonTable[name]["xMin"], buttonTable[name]["xMax"] do
            etc...
        end
    end
end
Now replace every "buttonTable[name]" with "value":
for name, value in pairs(buttonTable) do
    for y = value["yMin"], value["yMax"] do
        for x = value["xMin"], value["xMax"] do
            etc...
        end
    end
end
GamerNebulae #34
Posted 31 July 2013 - 07:00 AM
EDIT: HOLY CRAP Bit that was fast! (been ninja'd)

Well, this is your code, right?
for name, value in pairs(buttonTable) do
	for y = buttonTable[name]["yMin"], buttonTable[name]["yMax"] do
		for x = buttonTable[name]["xMin"], buttonTable[name]["xMax"] do
			etc...
		end
	end
end
Now replace every "buttonTable[name]" with "value":
for name, value in pairs(buttonTable) do
	for y = value["yMin"], value["yMax"] do
		for x = value["xMin"], value["xMax"] do
			etc...
		end
	end
end

Okay and just for esthetics, can I turn value and name around? It just looks cleaner ^^
apemanzilla #35
Posted 31 July 2013 - 07:02 AM
EDIT: HOLY CRAP Bit that was fast! (been ninja'd)

Well, this is your code, right?
for name, value in pairs(buttonTable) do
	for y = buttonTable[name]["yMin"], buttonTable[name]["yMax"] do
		for x = buttonTable[name]["xMin"], buttonTable[name]["xMax"] do
			etc...
		end
	end
end
Now replace every "buttonTable[name]" with "value":
for name, value in pairs(buttonTable) do
	for y = value["yMin"], value["yMax"] do
		for x = value["xMin"], value["xMax"] do
			etc...
		end
	end
end

Okay and just for esthetics, can I turn value and name around? It just looks cleaner ^^
If you mean change the for loop to for value, name in pairs, no you cant; otherwise you'll be using the wrong values
GamerNebulae #36
Posted 31 July 2013 - 07:50 AM
Can you give an example how it would work in my code?


for name, value in pairs(buttonTable) do
  for y = value["yMin"], value["yMax"] do
	for x = value["xMin"], value["xMax"] do
	  etc...
	end
  end
end

EDIT: haha! I'm a ninja! :ph34r:/>
EDIT: HOLY CRAP Bit that was fast! (been ninja'd)

Well, this is your code, right?
for name, value in pairs(buttonTable) do
	for y = buttonTable[name]["yMin"], buttonTable[name]["yMax"] do
		for x = buttonTable[name]["xMin"], buttonTable[name]["xMax"] do
			etc...
		end
	end
end
Now replace every "buttonTable[name]" with "value":
for name, value in pairs(buttonTable) do
	for y = value["yMin"], value["yMax"] do
		for x = value["xMin"], value["xMax"] do
			etc...
		end
	end
end

Maybe any ideas for the interactive part? Like I said, I want this to be a API that can be used by ANYONE. No matter how experienced they are in CC.

This is the code I have now:


for name, button in pairs(buttonTable) do
    for i = button["yMin"], button["yMax"] do
	    for j = button["xMin"], button["xMax"] do
		    if (i == yText and j == xText) then
			    mon.write(button["text"])
		    else
			    mon.write(" ")
		    end
	    end
    end
end
theoriginalbit #37
Posted 31 July 2013 - 08:04 AM
Maybe any ideas for the interactive part? Like I said, I want this to be a API that can be used by ANYONE. No matter how experienced they are in CC.
They shouldn't need to change any of that code… No matter their experience in CC… The point of APIs is to supply an interface to a program you have created, or create a section of useful functions, etc… They shouldn't need to be modified… They can have different data (i.e. buttons) but the functions shouldn't need to change…
GamerNebulae #38
Posted 31 July 2013 - 11:30 AM
Maybe any ideas for the interactive part? Like I said, I want this to be a API that can be used by ANYONE. No matter how experienced they are in CC.
They shouldn't need to change any of that code… No matter their experience in CC… The point of APIs is to supply an interface to a program you have created, or create a section of useful functions, etc… They shouldn't need to be modified… They can have different data (i.e. buttons) but the functions shouldn't need to change…

What I was trying to say was: it should be just one line of code they have to fill in and it is done. It should be dummy-proof. The question was: how can I detect if someone clicked on the coordinates of the button?
Lyqyd #39
Posted 31 July 2013 - 02:46 PM
Well, logically, you need a way to determine whether or not a click occurred in a specific area. This means that it must have occurred between the top and the bottom, and also between the left side and the right side. You will need to check that the click occurred to the right of the left edge, and also to the left of the right edge. Same with top and bottom.

Hint: one if statement with four comparisons joined by three ands.
GamerNebulae #40
Posted 31 July 2013 - 03:33 PM
Well, logically, you need a way to determine whether or not a click occurred in a specific area. This means that it must have occurred between the top and the bottom, and also between the left side and the right side. You will need to check that the click occurred to the right of the left edge, and also to the left of the right edge. Same with top and bottom.

Hint: one if statement with four comparisons joined by three ands.

Would this do?


while true do
  event, side, xPos, yPos = os.pullEvent()
    if event == os.pullEvent("monitor_touch") then
	  if (buttonTable[name]["xMin"] >= xPos and buttonTable[name]["xMax"] <= xPos and buttonTable[name]["yMin"] >= yPos and buttonTable[name]["yMax"] <= yPos) then
	  end
    end
end
Bubba #41
Posted 31 July 2013 - 04:22 PM
Would this do?


while true do
  event, side, xPos, yPos = os.pullEvent()
    if event == os.pullEvent("monitor_touch") then
	  if (buttonTable[name]["xMin"] >= xPos and buttonTable[name]["xMax"] <= xPos and buttonTable[name]["yMin"] >= yPos and buttonTable[name]["yMax"] <= yPos) then
	  end
    end
end
Close. Check your if statement again. You've reversed the comparisons. That would evaluate true if the user clicked anywhere but on the button.

e.g. Button at (5,10) with a width of 15 and height of 3
Click at 6,11

if (5 >= 6 and 20 <= 6 and 10 >= 11 and 9 <= 11) then
  --#All of these evaluate false despite the fact that the click was inside
GamerNebulae #42
Posted 31 July 2013 - 04:59 PM
Would this do?


while true do
  event, side, xPos, yPos = os.pullEvent()
	if event == os.pullEvent("monitor_touch") then
	  if (buttonTable[name]["xMin"] >= xPos and buttonTable[name]["xMax"] <= xPos and buttonTable[name]["yMin"] >= yPos and buttonTable[name]["yMax"] <= yPos) then
	  end
	end
end
Close. Check your if statement again. You've reversed the comparisons. That would evaluate true if the user clicked anywhere but on the button.

e.g. Button at (5,10) with a width of 15 and height of 3
Click at 6,11

if (5 >= 6 and 20 <= 6 and 10 >= 11 and 9 <= 11) then
  --#All of these evaluate false despite the fact that the click was inside

This?


while true do
  if (xPos >= buttonTable[name]["xMin"] and xPos <= buttonTable[name]["xMax"] and yPos >= buttonTable[name]["yMin"] and yPos <= buttonTable[name]["yMax"]) then
    action...
  end
end
Lyqyd #43
Posted 31 July 2013 - 06:43 PM
Yep, that looks correct. Obviously, though, you'd need something to pull the event to generate xPos and yPos, like you had in the previous snippet, but your if statement appears to be correct this time.
GamerNebulae #44
Posted 31 July 2013 - 06:52 PM
Yep, that looks correct. Obviously, though, you'd need something to pull the event to generate xPos and yPos, like you had in the previous snippet, but your if statement appears to be correct this time.

It will generate an xPos and yPos when it is activated by a player who clicks on the monitor. Now I need to come up with some colors, options for functionality, etc.
GamerNebulae #45
Posted 01 August 2013 - 06:56 AM
Gosh darnit! I am stuck at the part where I need to assign a function to that button. Anyone has suggestions?
apemanzilla #46
Posted 01 August 2013 - 07:05 AM

local function getClicked( xPos, yPos )
  if not (xPos and yPos) then
    error("expected number, got nil")
  end
  --Change the "buttons" part to the name of the array your using
  for name,_ in pairs(buttons) do
    if (xPos >= buttonTable[name]["xMin"] and xPos <= buttonTable[name]["xMax"] and yPos >= buttonTable[name]["yMin"] and yPos <= buttonTable[name]["yMax"]) then
    return name
  end
end
Basic usage:

local _,_,x,y = os.pullEvent("mouse_click")
local pressed = getClicked(x,y)
Somewhere below that you can use a row of if statements to determine what to do:

if pressed == "shutdown" then
  os.shutdown()
elseif pressed == "turtleon" then
  rednet.send(12,"start")
end
Change the conditions and actions to match your needs.
GamerNebulae #47
Posted 01 August 2013 - 07:21 AM

local function getClicked( xPos, yPos )
  if not (xPos and yPos) then
	error("expected number, got nil")
  end
  --Change the "buttons" part to the name of the array your using
  for name,_ in pairs(buttons) do
	if (xPos >= buttonTable[name]["xMin"] and xPos <= buttonTable[name]["xMax"] and yPos >= buttonTable[name]["yMin"] and yPos <= buttonTable[name]["yMax"]) then
	return name
  end
end
Basic usage:

local _,_,x,y = os.pullEvent("mouse_click")
local pressed = getClicked(x,y)
Somewhere below that you can use a row of if statements to determine what to do:

if pressed == "shutdown" then
  os.shutdown()
elseif pressed == "turtleon" then
  rednet.send(12,"start")
end
Change the conditions and actions to match your needs.

My question now is: Can I assign functions to a specific dimension in the array? Because like I said, I want an easier API than Dire's. I believe he made his way too complicated to use and I want a hassle free one:


button(..........., function())

Let's say I call the variable in that table ["action"], then it would look like this:


while true do
  event, side, xPos, yPos = os.pullEvent()
  if event == "monitor_touch" then
	if (xPos >= buttonTable[name]["xMin"] and xPos <= buttonTable[name]["xMax"] and yPos >= buttonTable[name]["yMin"] and yPos <= buttonTable[name]["yMax"]) then
	  buttonTable[name]["action"]
	end
  end
end
TheOddByte #48
Posted 01 August 2013 - 09:16 AM
Do you mean that you want to call a function from a table?

function test()
 print("Hello World!")
end

tFunction = {
[1] = {
name = test,
},
}

functionName = tFunction[1].name
functionName()
GamerNebulae #49
Posted 01 August 2013 - 09:23 AM
Do you mean that you want to call a function from a table?

function test()
print("Hello World!")
end

tFunction = {
[1] = {
name = test,
},
}

functionName = tFunction[1].name
functionName()

Yes, I want to recall a function from the buttonTable. But the one thing I don't get is, why do you put a table in a table? Tableception! :3
GamerNebulae #50
Posted 01 August 2013 - 07:18 PM
New problem! I tried to use the API by using this code:


os.loadAPI("monitor")
monitor.button("buttonOne", 3, 26, 2, 11, "button", colors.cyan, "pulse", "left", 5)

I got this error: monitor:33: index expected, got nil
Here is the code on pastebin: http://pastebin.com/kG0hxGhG
The code is far from done, but I'll finish it.
Bubba #51
Posted 01 August 2013 - 10:29 PM
New problem! I tried to use the API by using this code:


os.loadAPI("monitor")
monitor.button("buttonOne", 3, 26, 2, 11, "button", colors.cyan, "pulse", "left", 5)

I got this error: monitor:33: index expected, got nil
Here is the code on pastebin: http://pastebin.com/kG0hxGhG
The code is far from done, but I'll finish it.

This issue is best shown with some example code.

Let's say that I have a table named "people":

people = {}

I have decided that I want to make a new person with several attributes, so I try to do that like this:

people["Bubba"]["Name"] = "Bubba"
people["Bubba"]["Height"] = "5'11\""

This will give me an error: "index expected, got nil". Where is the problem? The problem is that I am trying to add values (Name, Height) to a table that does not yet exist.

To fix this, I would need to do the following:

people["Bubba"] = {}
people["Bubba"]["Name"] = "Bubba"
people["Bubba"]["Height"] = "5'11\""

So what I needed to do was create a new table inside of people that referred to "Bubba". Only after that can I add values to that table. Make sense?

Let's look at your code now:

function button(name, xMin, xMax, yMin, yMax, text, colorButton, action, parameterOne, parameterTwo, parameterThree)
        clear()
    buttonTable[name]["xMin"] = xMin
    buttonTable[name]["xMax"] = xMax
    buttonTable[name]["yMin"] = yMin
    buttonTable[name]["yMax"] = yMax
...
You immediately jump in to declaring properties of the button without first making a table for those properties to exist in. Try creating a table for those properties first and you should be good to go :)/>
Symmetryc #52
Posted 02 August 2013 - 02:16 AM
The thing to remember is that ipairs will only iterate sequential numerical indexes and it will be in order. However pairs will not have any order for the key/value pairs, but numerical indexes are iterated first AND in order!
Correct me if I'm wrong, but I believe it is only positive numerical indices that are in order.
theoriginalbit #53
Posted 02 August 2013 - 04:58 AM
Correct me if I'm wrong, but I believe it is only positive numerical indices that are in order.
With ipairs negative indexes aren't printed at all and in pairs they are in any random order. This is because negative indexes (and zero) are actually done via a key/value pair, just like when you do `[key] = value`… Thus negative and zero indexes aren't actually indexes and pairs.
GamerNebulae #54
Posted 02 August 2013 - 07:13 AM
Correct me if I'm wrong, but I believe it is only positive numerical indices that are in order.
With ipairs negative indexes aren't printed at all and in pairs they are in any random order. This is because negative indexes (and zero) are actually done via a key/value pair, just like when you do `[key] = value`… Thus negative and zero indexes aren't actually indexes and pairs.

Is that actually necessary? Because you can't enter negative coordinates. Or am I the stupid now?
GamerNebulae #55
Posted 02 August 2013 - 08:10 AM
Okay, new problem… The button isn't drawing. The drawing is happening in the lines between 56 and 67.
GamerNebulae #56
Posted 03 August 2013 - 04:22 PM
Dear readers,

I have been working on my Monitor API and I have booked some successes, but now I am debugging and testing the code and I ran into an issue. It's in the function button and it's about the button not wanting to draw.

http://pastebin.com/Z7mGqqP1
Lyqyd #57
Posted 03 August 2013 - 04:26 PM
Threads merged. Stick to one topic for all questions on a piece of code, please.

You're re-declaring the buttonTable each time you call the button function. Is the problem that you're only seeing one button drawn to the screen? It also looks like only the first character of your text might get drawn (as later iterations of the loop would overwrite the other characters).
GamerNebulae #58
Posted 03 August 2013 - 04:34 PM
Threads merged. Stick to one topic for all questions on a piece of code, please.

You're re-declaring the buttonTable each time you call the button function. Is the problem that you're only seeing one button drawn to the screen? It also looks like only the first character of your text might get drawn (as later iterations of the loop would overwrite the other characters).

It's not drawing anything. The monitor stays black. It doesn't even change colors. So if it would write over the code it would at least draw the outlines of the button. That is my problem.
Lyqyd #59
Posted 03 August 2013 - 04:37 PM
Ahh. You've used ipairs. I'm guessing the name variable isn't 1? Try switching to pairs instead.
GamerNebulae #60
Posted 03 August 2013 - 04:42 PM
Ahh. You've used ipairs. I'm guessing the name variable isn't 1? Try switching to pairs instead.

Thanks Lyqyd :)/> that worked. It was mentioned a few time around here and I thought I had to use it, but after all, it just confused me.
GamerNebulae #61
Posted 03 August 2013 - 06:14 PM
Dear reader,

I am working alot with for-loops at the moment and I was wondering if you could manipulate them in some way they can skip certain numbers.

For example: I am printing some text on a colored monitor, but the problem is, it's writing over the actual text. Now I want it to let the skip the specific spots reserved for text.

I hope you can help me.
Lyqyd #62
Posted 03 August 2013 - 06:28 PM
Stop making new topics for your questions about this code.

You might find it easier to go from xMax to xMin and use a step of -1 so that the coordinates of the rest of the text have already been iterated over by the time you get to the coordinates for the text.
GamerNebulae #63
Posted 03 August 2013 - 06:34 PM
Stop making new topics for your questions about this code.

You might find it easier to go from xMax to xMin and use a step of -1 so that the coordinates of the rest of the text have already been iterated over by the time you get to the coordinates for the text.

Sorry, thought it was a different question.
Lyqyd #64
Posted 03 August 2013 - 06:52 PM
Sure, you phrased it as a more general question, but you were asking because of the issue you were having with this piece of code, weren't you?
GamerNebulae #65
Posted 03 August 2013 - 07:55 PM
Sure, you phrased it as a more general question, but you were asking because of the issue you were having with this piece of code, weren't you?

Yes, I am sorry.
GamerNebulae #66
Posted 03 August 2013 - 08:09 PM
Well, I have been reading a ton of documentation about recalling functions within a table. I can't seem to figure this one out. I have now added the function pulse, wich looks like this:


function pulse(side, s)
  rs.setOutput(side, true)
  sleep(s)
  rs.setOutput(side, false

I am trying to make my API easier to use than the one DireWolf20 made. It should be possible to setup a button in one line actually, but I can't seem to figure out how to put the function inside the table. This is what I tried:


function button(name,xMin, xMax, yMin, yMax, text, colorButton, func())

If anyone has ideas, that would be great.
Bubba #67
Posted 03 August 2013 - 08:13 PM
You can pass a function to a table by simply giving it the variable name, but not calling it. For example:

local function passThis()
  print("Hello")
end

local function takeAFunction(func)
  func()
end

takeAFunction(passThis) --#Outputs "Hello"

You are trying to actually execute the function, which will pass the results rather than the actual function. Just give it the name and it'll work fine.
Lyqyd #68
Posted 03 August 2013 - 08:14 PM
When you are passing function values, you should put just the variable name. If you include the parentheses, it will call the function and pass the results instead of passing the function itself.
GamerNebulae #69
Posted 04 August 2013 - 04:20 AM
When you are passing function values, you should put just the variable name. If you include the parentheses, it will call the function and pass the results instead of passing the function itself.
You can pass a function to a table by simply giving it the variable name, but not calling it. For example:

local function passThis()
  print("Hello")
end

local function takeAFunction(func)
  func()
end

takeAFunction(passThis) --#Outputs "Hello"

You are trying to actually execute the function, which will pass the results rather than the actual function. Just give it the name and it'll work fine.

But how do I get the function to take variables? The function pulse needs 2 variables: side and s. Where do people fill in those and how can they have separate functions of pulse with different timings or sides?
Bubba #70
Posted 04 August 2013 - 07:15 AM
But how do I get the function to take variables? The function pulse needs 2 variables: side and s. Where do people fill in those and how can they have separate functions of pulse with different timings or sides?

You could pass those in as additional arguments to the function. it's a pain, I know.
GamerNebulae #71
Posted 04 August 2013 - 09:45 AM
But how do I get the function to take variables? The function pulse needs 2 variables: side and s. Where do people fill in those and how can they have separate functions of pulse with different timings or sides?

You could pass those in as additional arguments to the function. it's a pain, I know.

What would that look like? I can't really imagine it.
Bubba #72
Posted 04 August 2013 - 10:35 AM
But how do I get the function to take variables? The function pulse needs 2 variables: side and s. Where do people fill in those and how can they have separate functions of pulse with different timings or sides?

You could pass those in as additional arguments to the function. it's a pain, I know.

What would that look like? I can't really imagine it.


local function passThis(arg)
  print(arg)
end

local function takeFunction(func, arg)
    func(arg)
end
takeFunction(passThis, "hello")
takeFunction(passThis, "hello")
Lyqyd #73
Posted 04 August 2013 - 01:53 PM
If the values passed to them don't need to change over time, you can pass in an anonymous function that calls the actual function with the arguments you want:


function doThing(takes, three, arguments)
  --stuff here 
end

local funcTable = {}
funcTable[1] = function() return doThing("with", "its", "arguments") end

Notice that the last line declares a new function that just calls the function you actually want to call with the arguments you want it to have.
GamerNebulae #74
Posted 04 August 2013 - 04:53 PM
If the values passed to them don't need to change over time, you can pass in an anonymous function that calls the actual function with the arguments you want:


function doThing(takes, three, arguments)
  --stuff here
end

local funcTable = {}
funcTable[1] = function() return doThing("with", "its", "arguments") end

Notice that the last line declares a new function that just calls the function you actually want to call with the arguments you want it to have.

What you described earlier on was that it only could draw one button. I'll think of a solution about the functions later. First I want it working. I have been think of recalling the function in the while-loop. But that wouldn't work as it won't reach the clicky part.
GamerNebulae #75
Posted 05 August 2013 - 11:31 AM
Complete rewritten my code to work around the problem I described. Now it should draw every button on it's own. Problem is, I everytime get an error saying: monitor:24: attempt to index ? (a number value)

The code is over at pastebin: http://pastebin.com/Z7mGqqP1

I hope you guys can help me.
Lyqyd #76
Posted 05 August 2013 - 04:30 PM
You're still re-declaring buttonTable itself every time you add a button, so the tables is still going to only contain the last button you create. You need to declare buttonTable only once. As to the error message, you'd need to show us the code you're using with the API as well, not just the API.
GamerNebulae #77
Posted 05 August 2013 - 06:12 PM
You're still re-declaring buttonTable itself every time you add a button, so the tables is still going to only contain the last button you create. You need to declare buttonTable only once. As to the error message, you'd need to show us the code you're using with the API as well, not just the API.

This was the code I used:

os.loadAPI("monitor")
monitor.buttonTable("one", 3, 13, 2, 4, "button", colors.blue, colors.lightBlue)
Lyqyd #78
Posted 05 August 2013 - 08:25 PM
Line 19 passes the table that directly contains xMin, xMax, etc. to the drawing function, where you try to index values from it on each iteration. Instead of passing buttonTable[name], you'd need to pass buttonTable for your for loop in draw() to work correctly.
GamerNebulae #79
Posted 06 August 2013 - 03:55 PM
Hello everybody,

I am working alot on functions these days and with tables. It came to my knowledge that a table in a function can't be used throughout the whole program. Is there a way to "store" a table somewhere for a little while? I want to use it in a while-loop, but the problem is, is it is used in a function before it needs to go in a while-loop. Anyone ideas?
Lyqyd #80
Posted 06 August 2013 - 04:03 PM
Declare the table above the function.


local buttonTable = {}

function add(name, x, 6)
  buttonTable[name] = {
    x = x,
    y = y,
  }
end

Edit: Also, if you pull this crap a fourth time instead of asking in the topic that already exists for the code you're asking about, I'll put you on a permanent moderator preview.
GamerNebulae #81
Posted 06 August 2013 - 04:38 PM
Declare the table above the function.


local buttonTable = {}

function add(name, x, 6)
  buttonTable[name] = {
	x = x,
	y = y,
  }
end

Edit: Also, if you pull this crap a fourth time instead of asking in the topic that already exists for the code you're asking about, I'll put you on a permanent moderator preview.

And how would I recall the table in the loop? like this?


interactive(table) --# I put the table I saved in here
Lyqyd #82
Posted 06 August 2013 - 08:04 PM
What do you mean by "recall the table in the loop"? For this code, the table would simply be an upvalue, so it would be accessible by name like any other variable.
GamerNebulae #83
Posted 07 August 2013 - 03:32 PM
What do you mean by "recall the table in the loop"? For this code, the table would simply be an upvalue, so it would be accessible by name like any other variable.

I took a look at DireWolf's code and I did something he did and it worked. But the problem now is, that it only draws one button and strangely enough, it's the second one. This is the code: http://pastebin.com/Z7mGqqP1

And this is how I use the functions:

os.loadAPI("monitor")
monitor.buttonTable("one", 3, 13, 2, 4, "button", colors.red, colors.lime)
monitor.buttonTable("two", 3, 13, 6, 8, "button", colors.red, colors.lime)
monitor.interactive()
Lyqyd #84
Posted 07 August 2013 - 04:12 PM
Your declaration for buttonTable itself is still in the function that creates a single button. Why do you think it is a good idea to declare a new table for buttonTable and throw away the old table each time you call that function. You obviously ignored the advice I gave you in my post at the end of the previous page of this topic.
GamerNebulae #85
Posted 07 August 2013 - 04:19 PM
Your declaration for buttonTable itself is still in the function that creates a single button. Why do you think it is a good idea to declare a new table for buttonTable and throw away the old table each time you call that function. You obviously ignored the advice I gave you in my post at the end of the previous page of this topic.

I've been philosophizing a bit about it and looking at Dire's code about it and then I thought about it and indeed something was missing in the interactive part. It was the first index of the table called name. I thought it would work in the interactive part, because I declared all tables then.