!---------------------------------------------------------------------------- ! ! CoolMenu.Hug - Written by Mike Snyder - 2005 - Public Domain code. ! This is based partially on "menu()" from HugoLib.h. ! Feel free to use it, change it, do whatever you like. ! ! USAGE: ! ! First, initialize the menu with up to 9 dictionary entries: ! ! SetCoolMenu("Say Yes","Say No","Say Maybe","Say Nothing") ! ! Second, start the menu with number of leading (x offset) spaces. ! ! i = ShowCoolMenu(8) !Adds 8 spaces before all menu items. ! ! Alternately, you can add the "default choice" parameter for ESC/Q. ! This can be 1 to CoolOptCount (max options), but ShowCoolMenu will ! automatically adjust it if out of bounds. If out of bounds, or if ! no default choice number is given, the default is the last option. ! ! i = ShowCoolMenu(8,1) !8 spaces, default opt is first in list. ! ! Then, just check the return value of "i" to see what option was ! selected... (replace "i" with your own return variable). ! !---------------------------------------------------------------------------- array CoolOptList[9] global CoolOptCount = 0 global allow_menus = true global COOL_TEXTCOLOR global COOL_BGCOLOR global COOL_SELECTCOLOR global COOL_SELECTBGCOLOR !---------------------------------------------------------------------------- !Seems to be a Hugo limit of 16 locals and params per routine. So, need to !set the menu values before we actually show the menu. Defaule colors are !set here too. Change them if you like. ! routine SetCoolMenu(opt1,opt2,opt3,opt4,opt5,opt6,opt7,opt8,opt9) { CoolOptCount=0 if not opt1 = Nothing: CoolOptList[CoolOptCount++] = opt1 if not opt2 = Nothing: CoolOptList[CoolOptCount++] = opt2 if not opt3 = Nothing: CoolOptList[CoolOptCount++] = opt3 if not opt4 = Nothing: CoolOptList[CoolOptCount++] = opt4 if not opt5 = Nothing: CoolOptList[CoolOptCount++] = opt5 if not opt6 = Nothing: CoolOptList[CoolOptCount++] = opt6 if not opt7 = Nothing: CoolOptList[CoolOptCount++] = opt7 if not opt8 = Nothing: CoolOptList[CoolOptCount++] = opt8 if not opt9 = Nothing: CoolOptList[CoolOptCount++] = opt9 COOL_TEXTCOLOR = TEXTCOLOR COOL_BGCOLOR = BGCOLOR COOL_SELECTCOLOR = BRIGHT_WHITE COOL_SELECTBGCOLOR = CYAN } !---------------------------------------------------------------------------- ! Here are the guts of the menu. It should work inline regardless of whether ! the current font is proportional or fixed-width, because it will "locate" ! to the right row by printing empty rows from the top. This way, the menu ! can essentially be in-line. Note, though, that as of the current 3.1 Hugo, ! there are a couple quirks that ShowCoolMenu has to work around. First, ! there is no command to disable the "[More..."] prompt, although this is ! done automatically by the Hugo engine whenever "pause" is used, or whenever ! a "locate" is attempted past the bottom line of the screen. Second, there ! seems to be a bug in calculating display.cursor_row whenever the cursor ! was previously positioned higher on the display (i.e., not yet scrolling). ! For this reason, the menu adds about three buffer lines at the bottom of ! the menu, then erases the menu, to allow you to print results after the ! menu choice is made by the player. If you print more text than that, after ! the player picks a choice (before the next command prompt), then it's ! probably going to show the "[More...]" prompt. Also, if you have cleared ! the screen and moved the cursor up from the bottom, then the menu won't ! exactly appear right, because display.cursor_row is returning incorrect. ! routine ShowCoolMenu(leadspace,defchoice) { local i, selopt=1, topline, didscroll local drawmenu=true, pickopt=0, oldline local extralines topline = display.cursor_row !Optional default choice. If not supplied, then last option is default. if (defchoice < 1) OR (defchoice > CoolOptCount): defchoice = CoolOptCount if (allow_menus) { !We need to print extra lines to avoid possible scrolling. The menu !itself adds some space, but if there are fewer menu items, need more !buffer space. Allow for at least 3 lines of text after the menu. extralines = (8 - CoolOptCount) if (extralines < 3) : extralines = 3 didscroll = false for (i=0; i < CoolOptCount+extralines; i++) { oldline = display.cursor_row print "" if (display.cursor_row = oldline) { !We must have scrolled up by a line! topline-- !So adjust topline too. didscroll = true } } } while (true) { !Infinite loop until we exit. !Did the user already pick an option? if (pickopt > 0) { if (allow_menus) { EraseCoolMenu(topline,pickopt,leadspace) locate 1, 999 !A trick, to prevent "[More...]" prompt! LocateLine(topline + 2) } else { color BRIGHT_WHITE print number pickopt color TEXTCOLOR print "" !Extra line spacer } !!!return (pickopt) return CoolOptList[pickopt-1] } !Do we need to re-draw the menu? if (drawmenu) { DrawCoolMenu(topline,selopt,leadspace,false) drawmenu = false } pause select word[0] case 'N', 'n', DOWN_ARROW, RIGHT_ARROW { if (allow_menus) { selopt++ if (selopt > CoolOptCount): selopt = 1 drawmenu = true } } case 'P', 'p', UP_ARROW, LEFT_ARROW { if (allow_menus) { selopt-- if (selopt < 1): selopt = CoolOptCount drawmenu = true } } case 'Q', 'q', ESCAPE_KEY { if (allow_menus) { drawmenu = true } pickopt = defchoice } case ENTER_KEY { if (allow_menus) { drawmenu = true pickopt = selopt } else { pickopt = defchoice } } if word[0] >= '0' and word[0] <= '9' { i = word[0] - '0' if i = 0: i = 10 if (i>=1 and i<=CoolOptCount) { if (allow_menus) { drawmenu = true } selopt = i pickopt = i } } } } !---------------------------------------------------------------------------- !Unless we want to use the fixed-width font, like "menu" from hugolib.h, !we pretty much have to redraw the whole menu to make sure it all lines up. ! routine DrawCoolMenu(topline, curline, leadspace, pick_only) { local loop, FG, BG if (allow_menus) { LocateLine(topline) } else { print "" !Blank } for (loop=0; loop "; if (allow_menus) { color COOL_SELECTCOLOR, COOL_SELECTBGCOLOR !color YELLOW, BLUE print " "; number curline; " "; COLOR TEXTCOLOR, BGCOLOR print " "; } } } !---------------------------------------------------------------------------- ! Print spaces over the menu area, and then show just the selected option. ! routine EraseCoolMenu(topline, selopt, leadspace) { local loop LocateLine(topline) !Erase all the menu options, plus the prompt line. !for (loop=0; loop<=CoolOptCount; loop++) { for (loop=0; loop<=CoolOptCount+1; loop++) { if (loop < CoolOptCount+1) { print to (display.linelength - 1) } else { print to (display.linelength - 1); } } DrawCoolMenu(topline, selopt, leadspace, true) } !---------------------------------------------------------------------------- !Perform a "locate" on the proportional screen, since the Hugo locate only !works with fixed-width font coordinates. Basically, we go to the top and !skip down for however many lines specified. Not elegant, but it works! !This assumes that proportional printing is already turned on. ! routine LocateLine(line) { local i : locate 1, 1 for (i=1; i