-- Universal Menu script -- by Spirikoi -- Please write my pseudo on your script if you use those functions menu = { -- ">" to open an other window or "%" to execute a function ['1']={">",">",">"}, ['1.1']={"%","%","%",">"}, ['1.2']={"%"}, ['1.3']={"%"}, ['1.1.4']={"%","%"} } menuLabels = { ['1.1']="Menu 1",['1.2']="Menu 2",['1.3']="Menu 3", ['1.1.1']="Action 1",['1.1.2']="Action 2",['1.1.3']="Action 3",['1.1.4']="Menu", ['1.2.1']="Action 1", ['1.3.1']="Action 1", ['1.1.4.1']="Action 1",['1.1.4.2']="Action 2" } menuIcons = { -- you may put images (16*16) where you want ['1.1'] = image.new("\016\000\000\000\016\000\000\000\000\000\000\000 \000\000\000\016\000\001\000\222\251\189\247\182\2063\186\156\239\222\251S\190\149\202\189\247\222\251\222\251\222\251\222\251\222\251\222\251\222\251\222\251u\198\248\2103\190\189\247\222\251\018\186\025\215\149\202\222\251\222\251\222\251\222\251\222\251\222\251\222\251:\227\150\198[\2233\190\189\247\222\251\018\186[\223u\194:\227\222\251\222\251\222\251\222\251\222\251\222\251t\198\025\215:\2193\190\157\243\189\2473\190;\223\216\206t\198\222\251\222\251\222\251\222\251\222\251\222\251S\190\025\219\025\215\249\210S\1903\190:\223;\223\216\206S\190\222\251\222\251\222\251\222\251\222\251\222\251T\194\248\214\025\215\216\210\216\206\025\219:\223\249\214\182\202T\194\222\251\222\251\222\251\222\251\222\251\222\251\025\223u\198\216\210\216\210\216\210\216\210\216\210\215\2063\1909\227\222\251\222\251\222\251\222\251\222\251\222\251\222\247T\194u\198\183\206\183\206\183\206\183\206T\190T\194\189\247\222\251\222\251\222\251\222\251\222\251\222\251\222\251\222\251\215\214t\194\183\206\182\206S\190\215\214\222\251\222\251[\219[\219\222\251\222\251[\219\157\235\222\251\222\251\222\251\241\177\215\210\182\202\241\177\189\247\222\251\222\251\151\174\244\133\222\251\222\251\244\137\222\251\222\251\222\251\222\251\241\177\025\219\183\206\241\177\189\247\222\251\222\251\222\251\244\133\151\174\151\174\157\235\222\251\222\251\222\251\222\251\241\177:\223\216\210\241\177\189\247\222\251\222\251\222\251[\219\244\133\151\174\222\251\222\251\222\251\222\251\222\251\241\177:\223\249\210\241\177\189\247\222\251\222\251\222\251\222\251\244\133\021\146\222\251\222\251\222\251\222\251\222\251\241\177[\227\026\215\241\177\189\247\222\251\222\251\222\251\216\186\157\235\244\133[\219\222\251\222\251\222\251\222\251\241\177\092\227\026\215\241\177\189\247\222\251\222\251\190\243\216\186\222\251\151\174\244\133\222\251\222\251\222\251\222\251\017\182\241\177\241\177\017\182\189\247\222\251\222\251\244\133[\219\222\251[\219\244\133W\162") } calc = {} function menuActions(num) -- Put here all the functions the menu must execute if num == "1.1.1" then -- put here a function elseif num == "1.1.2" then -- here an other end -- etc. end function menuCommands(act,ch) if act == "open" then menuState = true menuPos = {1,1} elseif act == "close" then menuState = false elseif act == "left" or act == "escape" then if textMenuPos(-1) == "1" then if act == "escape" then menuCommands("close") end else table.remove(menuPos,table.getn(menuPos)) end elseif act == "up" and menuPos[table.getn(menuPos)] > 1 then menuPos[table.getn(menuPos)] = menuPos[table.getn(menuPos)] - 1 elseif act == "down" and menuPos[table.getn(menuPos)] ~= table.getn(menu[textMenuPos(-1)]) then menuPos[table.getn(menuPos)] = menuPos[table.getn(menuPos)] + 1 elseif act == "enter" or act == "right" and menuPos[table.getn(menuPos)] ~= 0 then if menu[textMenuPos(-1)][menuPos[table.getn(menuPos)]] == "%" then if act == "enter" then menuCommands("close") menuActions(textMenuPos(0)) end else table.insert(menuPos,1) end elseif act == "char" then local a = string.find("123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",string.upper(ch)) if a ~= nil and a <= table.getn(menu[textMenuPos(-1)]) then menuPos[table.getn(menuPos)] = a menuCommands("enter") end end end function findMax(a) -- Taken on the net local mi = 1 --index of max value local m = a[mi] --max value for i, val in ipairs(a) do --can use pairs() as well, ipairs() indicates an array-like table if val > m then mi = i m = val end end return m --neat feature of lua, can return multiple values end function textMenuPos(pos) -- Return the 1.X.X.X position. Pos can be negative or null local text = "1" if pos <= 0 then pos = table.getn(menuPos) + pos elseif pos > table.getn(menuPos) then pos = table.getn(menuPos) end for i=2, pos do text = text.."."..tostring(menuPos[i]) end return text end function drawMenu() calc = {} local ref = {0,0} local charList = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" for i=1, table.getn(menuPos)-1 do local list = {} local margin = 0 -- Script for k=1, table.getn(menu[textMenuPos(i)]) do table.insert(list,platform.gc():getStringWidth(menuLabels[textMenuPos(i).."."..tostring(k)])) end local width = findMax(list) + 30 for a=1,table.getn(menu[textMenuPos(i)]) do if menuIcons[textMenuPos(i).."."..tostring(a)] ~= nil then margin = 18 end end local height = 18*table.getn(list) if ref[1] == platform.window:width() then ref[1] = 0 elseif ref[1] + width + margin > platform.window:width() then ref[1] = platform.window:width() - width - margin end if ref[2] + height > platform.window:height() then ref[2] = platform.window:height() - height end if platform.isColorDisplay() then setColor("white") else setColor("silver") end platform.gc():fillRect(ref[1],ref[2],width + margin,height) for j = 1, table.getn(menu[textMenuPos(i)]) do if textMenuPos(i).."."..tostring(j) == textMenuPos(0) then if platform.isColorDisplay() then setColor("royalblue") else setColor("") end platform.gc():fillRect(ref[1],ref[2]+18*(j-1),width + margin,18) setColor("white") elseif j == menuPos[i+1] then setColor("royalblue",120) platform.gc():fillRect(ref[1],ref[2]+18*(j-1),width + margin,18) setColor("") else setColor("") end if menu[textMenuPos(i)][j] == ">" then platform.gc():drawString(string.uchar(0x25b6),ref[1] + width + margin - 10,ref[2]+18*(j-1)-2,"top") end platform.gc():drawString(string.sub(charList,j,j),ref[1]+3 + margin,ref[2]+18*(j-1)-2,"top") platform.gc():drawString(": "..menuLabels[textMenuPos(i).."."..tostring(j)],ref[1]+10 + margin,ref[2]+18*(j-1)-2,"top") if menuIcons[textMenuPos(i).."."..tostring(j)] ~= nil then platform.gc():drawImage(menuIcons[textMenuPos(i).."."..tostring(j)],ref[1] + 1,ref[2]+18*(j-1)+1) end end setColor("") platform.gc():drawRect(ref[1],ref[2],width + margin,height) table.insert(calc,{textMenuPos(i),ref[1],ref[2],ref[1]+width + margin,ref[2]+height}) ref = {ref[1] + width + margin,ref[2]+18*(menuPos[i+1]-1)} end end function getMouseBack(x,y) local i = table.getn(calc) while i > 0 do if calc[i][2] <= x and x <= calc[i][4] and calc[i][3] + 1 <= y and y <= calc[i][5] then if i == table.getn(menuPos)-1 then menuPos[table.getn(menuPos)] = math.floor( (y-calc[i][3]-1)/18) + 1 end i=0 end i = i-1 end screenRefresh() end function clickMouseBack(x,y) local i = table.getn(calc) local j = i while i > 0 do if calc[i][2] <= x and x <= calc[i][4] and calc[i][3] + 1 <= y and y <= calc[i][5] then if i == j then menuCommands("enter") screenRefresh() else for k=i+1,j do table.remove(menuPos,i+1) end on.mouseMove(x,y) end i=0 end i = i-1 end if i==0 then menuCommands("close") end end -- Other functions function setColor(theColor,Alpha) -- It's a "Better lua API" script that I've modified if Alpha == nil then platform.gc():setAlpha(255) else platform.gc():setAlpha(Alpha) end theColor = string.lower(theColor) platform.gc():setColorRGB(0,0,0) -- set black as default is nothing else valid is found if theColor == "blue" then platform.gc():setColorRGB(0,0,255) elseif theColor == "brown" then platform.gc():setColorRGB(165,42,42) elseif theColor == "cyan" then platform.gc():setColorRGB(0,255,255) elseif theColor == "darkblue" then platform.gc():setColorRGB(0,0,139) elseif theColor == "darkred" then platform.gc():setColorRGB(139,0,0) elseif theColor == "fuchsia" then platform.gc():setColorRGB(255,0,255) elseif theColor == "gold" then platform.gc():setColorRGB(255,215,0) elseif theColor == "gray" or theColor == "grey" then platform.gc():setColorRGB(127,127,127) elseif theColor == "green" then platform.gc():setColorRGB(0,128,0) elseif theColor == "lightblue" then platform.gc():setColorRGB(173,216,230) elseif theColor == "lightgreen" then platform.gc():setColorRGB(144,238,144) elseif theColor == "magenta" then platform.gc():setColorRGB(255,0,255) elseif theColor == "maroon" then platform.gc():setColorRGB(128,0,0) elseif theColor == "navyblue" then platform.gc():setColorRGB(159,175,223) elseif theColor == "orange" then platform.gc():setColorRGB(255,165,0) elseif theColor == "palegreen" then platform.gc():setColorRGB(152,251,152) elseif theColor == "pink" then platform.gc():setColorRGB(255,192,203) elseif theColor == "purple" then platform.gc():setColorRGB(128,0,128) elseif theColor == "red" then platform.gc():setColorRGB(255,0,0) elseif theColor == "royalblue" then platform.gc():setColorRGB(65,105,225) elseif theColor == "salmon" then platform.gc():setColorRGB(250,128,114) elseif theColor == "seagreen" then platform.gc():setColorRGB(46,139,87) elseif theColor == "silver" then platform.gc():setColorRGB(192,192,192) elseif theColor == "turquoise" then platform.gc():setColorRGB(64,224,208) elseif theColor == "violet" then platform.gc():setColorRGB(238,130,238) elseif theColor == "white" then platform.gc():setColorRGB(255,255,255) elseif theColor == "yellow" then platform.gc():setColorRGB(255,255,0) end end -- Events function on.timer() end function on.mouseDown(x,y) end function on.mouseUp(x,y) if menuState then clickMouseBack(x,y) end end function on.mouseMove(x,y) if menuState then getMouseBack(x,y) end end function on.arrowKey(key) on.event(key) end function on.charIn(ch) on.event(ch,"char") end function on.enterKey() on.event("enter") end function on.escapeKey() on.event("escape") end function on.tabKey() on.event("tab") end function on.deleteKey() on.event("delete") end function on.backspaceKey() on.event("backspace") end function on.returnKey() on.event("return") end function on.contextMenu() on.event("contextmenu") end function on.backtabKey() on.event("backtab") end function on.clearKey() on.event("clear") end function on.help() on.event("help") end function on.event(event,typ) event = string.lower(event) if not menuState then if event == "escape" or event == "contextmenu" then menuCommands("open") end elseif menuState then if event == "up" or event == "down" or event == "left" or event == "right" or event == "enter" or event == "escape" then menuCommands(event) end if typ == "char" then menuCommands("char",event) end end screenRefresh() end function screenRefresh() platform.window:invalidate() end function on.create() menuState = false end -- Paint function on.paint(gc) local str = {"Universal Menu by Spirikoi","Echap or ctrl+menu to open"} setColor("red",200) gc:drawString(str[1],(platform.window:width()-gc:getStringWidth(str[1]))/2,platform.window:height()/2-10) gc:drawString(str[2],(platform.window:width()-gc:getStringWidth(str[2]))/2,platform.window:height()/2+10) if menuState then drawMenu() end -- Always put it in last if you want the menu to be on the foreground end