First question: The easiest route is to use panels. If you're
really trying to customize your menus, and you have no need for pagination, panels will give you the most flexibility at the price of being very low-level. That means, all of the "nice" features that menus have, such as pagination, item info/text abstraction, and cross-style consistency, won't exist. You just add text to the panel and you're done.
If you decide that managed menus are the way to go, read on. The rest of this post deals with the rendering algorithm and I will answer your second question in a follow-up post.
You can hook the per-item rendering algorithm with MenuAction_DisplayItem and the title-rendering portion with MenuAction_Display. That said, you need to understand how the rendering algorithm works to go further:
- First, it decides how many items can be displayed on the current page. That number will be less than or equal to 10 (let's say it's equal to N).
- Then it will go through every item on the menu until it meets a certain set of credentials. The credential process:
- GetMenuItem() is called to retrieve information about the item.
- The MenuHandler is called with MenuAction_DrawItem -- this is so the plugin can override the style normally retrieved by GetMenuItem().
- If the item cannot be drawn by the style, it will be ignored. For radio menus, that's having ITEMDRAW_IGNORE, or ITEMDRAW_DISABLED|ITEMDRAW_CONTROL. For VGUI menus, that's having ITEMDRAW_RAWLINE, ITEMDRAW_NOTEXT, ITEMDRAW_SPACER, or ITEMDRAW_DISABLED.
- If the item has ITEMDRAW_IGNORE, it is ignored.
- If the item has ITEMDRAW_RAWLINE, it is ignored.
- Otherwise, the item is stored in an array of "valid" items.
- Once the menu has N items, going from item X to X+N, it will then try to match items X-1 and X+N+1 to determine whether there are other pages. That uses the same "credential" process.
- The menu is finally ready to draw. It creates a new Panel object, then for each of the N items:
- The MenuHandler is called with MenuAction_DisplayItem. This allows the text to be redrawn.
- The text is added to the Panel.
- Once all items are added to the panel, the MenuHandler is called with MenuAction_Display. If no title is set on the Panel after the handler concludes, then a default title is applied.
- The panel is returned from the rendering algorithm, and the menu subsystem displays it to the client.
As you can see, it's an involved, complicated process, completely dedicated to having uniform-looking menus. Letting users attach raw lines of text to a given menu greatly complicates the design -- the rendering algorithm would basically need a complete rewrite. The only viable solution would be to have "sub-items" of text that get drawn along with an item. If we do add that, it won't be for 1.0.0. It's further complicated by the fact that the Valve menu style doesn't really support raw lines of text (other than cramming the button full with one blurb).
That said, we can add a MenuAction_DisplayItemEx callback. This would be a "serious users only" callback that would let you
inject raw text during the drawing process. You have to be clever about it, but basically the idea is that the renderer would say, "draw item #2 for me." You could then draw whatever you wanted via the Panel it gives you. (MenuAction_DisplayItem is a simplified handler which just lets you change the selectable text, rather than have full underlying Panel control.)
__________________