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

[Help] Advanced menu.

Started by Cranium, 08 August 2012 - 06:41 PM
Cranium #1
Posted 08 August 2012 - 08:41 PM
I am trying to make a fancy schmancy advanced-ish menu for my master control program, and I am at a total loss. I am trying to combine the left to right scrolling of this function:

function yN()
local n=1
while true do
local x, y=term.getCursorPos()
term.clearLine()
if n==1 then write(">YES<   NO") else write (" YES   >NO<") end
term.setCursorPos(x, y)
a, b=os.pullEvent()
while a~="key" do a, b=os.pullEvent() end
if b==203 and n==2 then n=1 end
if b==205 and n==1 then n=2 end
if b==28 then print("") break end
end
if n==1 then return true end
if n==2 then return false end
return false
end
with the up and down options of this one:

function opt(m)
n=1
l=#m
while true do
term.clear()
term.setCursorPos(1,2)
for i=1, l, 1 do
if i==n then print(i, " ["..m[i].."]") else print(i, " ", m[i]) end
end
a, b= os.pullEventRaw()
if a == "key" then
if b==200 and n>1 then n=n-1 end
if b==208 and n<=l then n=n+1 end
if b==28 then break end
end
end
term.clear() term.setCursorPos(1,1)
return n
end
Both of these were lifted off of the tutorials section of the forum, and I am fairly "confident" with using either of these separately, but I have no idea how to do that. I am trying to make a menu that has several options across, and maybe three options up/down.

I AM SOOOO CONFUSED AT THIS CODE! Also, I suck at math. ;)/>/>
Pharap #2
Posted 09 August 2012 - 06:21 AM
Ok, firstly it depends how you are arranging your pages.
Secondly I recommend assigning each 'button' on your screen an X and Y coordinate.

Draw the console, with the option appearing highlighted depending on the X and Y of your 'cursor'
eg:
button1 has an x of 1 and a y of 1, so does your cursor, so button1 is highlighted
button2 has an x of 1 and a y of 2, your cursor has x of 1 and y of 1, so button2 isn't highlighted

after the drawing, test for keyboard input
adjust the data accordingly.

loop the system so it redraws/switches to a different function.

A quick(tiny) demo:

curx ,cury=term.getCursorPos()

btn1x = 1
btn1y = 1
btn2x = 1
btn2y = 2
--in your actual program, put these in a table or
--make the lua equivalent of an object if you know about object orientation

while true do
if curx==btn1x and cury==btn1y then
print("   [Button1]   Button2    ")
elseif curx==btn2x and cury==btn1y then
print("    Button1   [Button2]   ")
end

e, k = os.pullEvent()
if e == "Key" then
 if k==203 then curx = curx - 1 --left
 elseif k==205 then curx = curx + 1 --right
 elseif k==200 then cury = cury - 1 --up
 elseif k==208 then cury = cury + 1 --down
 elseif k==28 then return --enter
 end
end
Cranium #3
Posted 09 August 2012 - 02:39 PM
WOW, thank you. This will help me go towards actually getting the program I need. Great starting point, by the way. I was totally lost.
Pharap #4
Posted 10 August 2012 - 01:20 AM
WOW, thank you. This will help me go towards actually getting the program I need. Great starting point, by the way. I was totally lost.

No problem. I'm taking a GameDev course in college right now, so I gotta know this stuff ;)/>/>
If menus, graphics or anything game-related is needed, I'm your man. Just don't ask me about Java, it's one of the languages on my todo list.
If you ever have a big project idea but are stuck on code or need a partenr, I'm also free to help (I have a few project ideas of my own).
Also, I saw your 8 ball thing and I've got to admit, it's literally the only program on this site that has interested me enough to try it out :(/>/> with a bit of graphics tweaking it would be a brilliant little app.
Cranium #5
Posted 10 August 2012 - 05:11 PM
Hrm. Got stuck with what I have so far. I think I understand the syntax(for the most part), but now I am having problems with it actually executing. It's not actually doing anything, and I don't know what I did wrong…

function menuOpt()
curx ,cury=term.getCursorPos()
local btn1 = {"1","1","Production"}
local btn2 = {"2","1","Reactor Control"}
local btn3 = {"1","2","Lights"}
local btn4 = {"2","2","Check System Status"}
while true do
--local curx=btn1[1]
--local cury=btn1[2]
term.setCursorPos(1,8)
if curx==btn1[1] and cury==btn1[2] then
term.setCursorPos(1,8)
print("   [",btn1[3],"]   ",btn2[3],"    ")
elseif curx==btn2[1] and cury==btn2[2] then
term.setCursorPos(1,8)
print("   ",btn1[3],"   [",btn2[3],"]    ")
elseif curx==btn3[1] and cury==btn3[2] then
term.setCursorPos(1,9)
print("  [",btn3[3],"]   ",btn4[3],"	 ")
elseif curx==btn4[1] and cury==btn4[2] then
print("   ",btn3[3],"   [",btn4[3],"]    ")
else
print("  [",btn1[3],"]   ",btn2[3],"	 ")
print("   ",btn3[3],"    ",btn4[3],"	 ")
end
e, k = os.pullEvent("key")
if k==203 then curx = curx - 1 --left
elseif k==205 then curx = curx + 1 --right
elseif k==200 then cury = cury - 1 --up
elseif k==208 then cury = cury + 1 --down
elseif k==28 then return --enter
end

if curx == 1 and cury == 1 then return "1" end
if curx == 2 and cury == 1 then return "2" end
if curx == 1 and cury == 2 then return "3" end
if curx == 2 and cury == 2 then return "4" end
end
end
Pharap #6
Posted 11 August 2012 - 02:23 AM
Ok, I had a quick scan through and a test out.

Your first issue is that you created it as a function and did not call the function, so I added the call code (at the bottom, if you call a function before it is read in lua, the program won't work)

After that, you had a few issues.
Firstly your returns were in your loop, so the loop almost always ended before enter was pressed.
Secondly you had a return for enter where you wanted a break (break terminates loop, return terminates function or program, it might work on a loop, but I'm pretty sure it doesn't since loops aren't intended to return a value).
After that, you had all the conditions in one if, meaning only one of your 2 lines would get printed. I fixed this by having two if statements and both return the line's both unselected form if neither statement is true.
You also forgot to clear the screen before repeating, thus chaining the text on the console as opposed to redrawing it.

I also added something printing the word Options before the two lines to test if something was causing a bug. It helped, I left it in there anyway but feel free to remove it.

I've pretty much done most of your bug checking and you've definitely got the right idea about how to do things, most of your bugs are just silly little overlooked things as opposed to anything major.

Next step is to stop the selector disappearing.
Eg on the button responses, stop the counter adding over a certain number. If you are going to only have 4, you could settle for absolute numbers, but if you are planning to have more than 4 options, you need to do a bit of 'predictive coding'.

If you get stuck again, just ask.

I'll send you a link to the code in a message, then if you want to make it public, it's your decision.
KaoS #7
Posted 12 August 2012 - 08:58 AM
I made a function to generate a menu once but can't remember where I put it, let me try again, it is very useful as you can make multiple different menus by just making a table of the choices and calling the function


	function generatemenu(choices, results, spacing)
	spacing=tonumber(spacing) or 7 - the horozontal spacing between selections
	if type(choices)~="table" or type(results)~="table" then
	print("ERROR GENERATING MENUnINPUT INCORRECT")
	end
	local selectedx=1
	local selectedy=1
	while true do
	for y=1,#choices do --to print out the menu items and select the correct one
	  for x=1,#choices[y] do
	   if x==selectedx and y==selectedy then
	    term.setCursorPos(x*spacing-spacing,y)
	    write(">"..choices[y][x].."<")
	   else
	    term.setCursorPos(x*spacing-spacing+1,y) end
	    write(choices[y][x])
	   end
	  end
	end
	
	while true do
	local event,param1=os.pullevent("key")
	  if param1==203 and selectedx>1 then selectedx=selectedx-1 break
	  elseif param1==205 and selectedx<#choices[selectedy] then selectedx=selectedx+1 break
	  elseif param1==200 and selectedy>1 then selectedy=selectedy-1 break
	  elseif param1==208 and selectedy<#choices then selectedy=selectedy+1 break
	  elseif param1==28 then return loadstring(results[y][x])()
	  end
	end
	if selectedx>#choices[y] then selectedx=#choices[y] end -- in case when you move down you are moving into a shorter row, this will put your selection at the end of that row
	end
	end
	

you call the function with 2 or 3 parameters, the first and second are tables in the following format


	choices={}
	for i=1,5 do --add rows
	choices[i]={}
	for a=1,5 do --add columns to each row
	choices[i][a]="the choice that will show at this position (a,i) in your menu"
	end
	end
	

so each value in choices is a table, each one of those tables is a row and each value in those tables is a column in that row, essentially we are making a co-ordinate based menu in the format choices[y][x]

the 'results' table is the same as the choices in how it is structured but it is a table of functions to call for each menu option if it is selected, the values in this table must be surrounded by quotes as we are using loadstring to call them, if we did not you would just make the value the function name and do not include brackets after it, the problem with this is that you cannot put multiple functions in it (so we use loadstring)

here is an example of its use, a one line menu


	mytable={}
	mytable[1]={} --row one
	mytable[1][1]="choice1" --first choice
	mytable[1][2]="choice2" --second choice
	mytable[1][3]="choice3" --third choice
	myresults={}
	myresults[1]={}
	myresults[1][1]="term.clear() term.setCursorPos(1,1) print('you selected the first choice')"
	myresults[1][2]="term.clear() term.setCursorPos(1,1) print('you selected the second choice')"
	myresults[1][3]="term.clear() term.setCursorPos(1,1) print('you selected the third choice')"
	generatemenu(mytable,myresults,10)
	
KaoS #8
Posted 12 August 2012 - 09:00 AM
I have not tested it yet but you can either test &amp; fix it or use the concept, if you do not want to use a separate table for each row then I can adapt it to use 1 table with fixed row lengths if you like
Pharap #9
Posted 12 August 2012 - 09:19 AM
I have not tested it yet but you can either test &amp; fix it or use the concept, if you do not want to use a separate table for each row then I can adapt it to use 1 table with fixed row lengths if you like

Sorry, you got here a few days late, the code I gave him was tested and I think he used it in the end.
KaoS #10
Posted 12 August 2012 - 09:48 AM
ahk, well hopefully it can help someone… if anyone needs help with it just PM me
KaoS #11
Posted 12 August 2012 - 11:58 AM
ok, I have tested and corrected it, there were a few incorrect references etc etc, here is the correct code with an example on a 2 line use

Code:
Spoiler
function generatemenu(choices, results, spacing)
spacing=tonumber(spacing) or 7
if type(choices)~="table" or type(results)~="table" then
print("ERROR GENERATING MENUnINPUT INCORRECT")
return nil
end
local selectedx=1
local selectedy=1
while true do
term.clear()
for y=1,#choices do
for x=1,#choices[y] do
if x==selectedx and y==selectedy then
term.setCursorPos(x*spacing-spacing+1,y)
write(">"..choices[y][x].."<")
else
term.setCursorPos(x*spacing-spacing+2,y)
write(choices[y][x])
end
end
end


while true do
local event,param1=os.pullEvent("key")
if param1==203 and selectedx>1 then
selectedx=selectedx-1
break
end
if param1==205 and selectedx<#choices[selectedy] then
selectedx=selectedx+1
break
end
if param1==200 and selectedy>1 then
selectedy=selectedy-1
break
end
if param1==208 and selectedy<#choices then
selectedy=selectedy+1
break
end
if param1==28 then
return loadstring(results[selectedy][selectedx])()
end
end
if selectedx>#choices[selectedy] then
selectedx=#choices[selectedy]
end
end
end

Example:
Spoiler
mytable={}
mytable[1]={}
mytable[1][1]="choice1"
mytable[1][2]="choice2"
mytable[1][3]="choice3"
mytable[2]={}
mytable[2][1]="choice4"
mytable[2][2]="choice5"
mytable[2][3]="choice6"

myresults={}
myresults[1]={}
myresults[1][1]="term.clear() term.setCursorPos(1,1) print('you selected the first choice')"
myresults[1][2]="term.clear() term.setCursorPos(1,1) print('you selected the second choice')"
myresults[1][3]="term.clear() term.setCursorPos(1,1) print('you selected the third choice')"
myresults[2]={}
myresults[2][1]="term.clear() term.setCursorPos(1,1) print('you selected the fourth choice')"
myresults[2][2]="term.clear() term.setCursorPos(1,1) print('you selected the fifth choice')"
myresults[2][3]="term.clear() term.setCursorPos(1,1) print('you selected the sixth choice')"

generatemenu(mytable,myresults,10)
spysean1499 #12
Posted 07 May 2013 - 04:11 AM
can somewon pst some coad that i can edit and is clickable?(ps make it oveos where 2 edit im a MEGA noob computercraft)i need basicly a tutural