Thread: Best "Menu" method?

  1. #1
    Registered User SSJMetroid's Avatar
    Join Date
    Dec 2005
    Posts
    12

    Best "Menu" method?

    I was just wondering.. What would be the best code method for creating - say - a number of menus that you can navigate around? Thanks for any info on this subject in advance.

  2. #2
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    GUI or console?
    Sent from my iPad®

  3. #3
    Registered User SSJMetroid's Avatar
    Join Date
    Dec 2005
    Posts
    12
    GUI, please. ^^

  4. #4
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Can you be more specific on what type of libraries you're using to create this?
    Sent from my iPad®

  5. #5
    Registered User SSJMetroid's Avatar
    Join Date
    Dec 2005
    Posts
    12
    Ah, I purposely didn't specify. I'm just talking about theoretically, if you're making any sort of program that has menu's in it, how would you go about doing it in the most efficient way? I hope I clearified that enough. >_<

    I'm not really looking for "how would you do it with _____ library, etc... " I can try and figure that part out myself.
    Last edited by SSJMetroid; 12-06-2005 at 05:01 PM.

  6. #6
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Wellll, if you really don't want to code anything much but have a GUI fast, use the Win32 API, its GUI heaven..

    Other than that, I don't know much about GUI work.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  7. #7
    Registered User SSJMetroid's Avatar
    Join Date
    Dec 2005
    Posts
    12
    Hmmm, it's a good thought, but I wasn't really intending to use "Windows API." :P

    Never intended for it to be made fast. XD

  8. #8
    mov.w #$1337,D0 Jeremy G's Avatar
    Join Date
    Nov 2001
    Posts
    704
    I thought this would be an opertune time to demonstrate how a menu system can get out of control. The concept I had going here was very solid, but through coding I ended up adding a lot of functionality "hacks" that made the system kinda combursom.

    EVENTS: drive everything , including the UI so, heres the class header
    Code:
    ////////////////////////////////////
    // event.h
    // game processes class file
    // all entities that require some sort of 
    // processing or handling inherit the event object
    #ifndef PR_EVENT
    #define PR_EVENT
    
    #include "global.h"
    
    
    
    // Objects that need to be managed will
    // inherit this as base class
    class CEventNode {
    	friend class CEventList;
    public:
    	CEventNode();
    	~CEventNode();
    	void setThread(CThread *thread);
    	virtual bool process(CEventList *owner) = 0; // if a process returns true it was handled and should be removed
    							// else it remains in teh que for the next game tick
    
    protected:
    	__int64 spawn; // onlything important relavent to all processes is when it was spawned
    				   // anything else is defined in subclasses
    	static long int instanceCount;
    	long int id;   // event id - I have no idea of the potential ammount of events in a single game long should be fine
    	CEventNode * next; // points to next event to be processed
    	CEventNode * prev; // points to prev event (easier removal of nodes)
    	CThread *thread; // thread spawning
    };
    
    class ListCleanUp : public CEventNode { // a node that on process tells the managing list it's empty
    public:
    	ListCleanUp(bool fullclean){ this->fullclean = fullclean; };
    	~ListCleanUp() {};
    	bool process(CEventList *owner);
    private:
    	bool fullclean;
    };
    
    // Special CEventNode() that handles setting or removing a CThread 
    // depreciated ?
    class CEventNodeThreader : public CEventNode {
    public: 
    	CEventNodeThreader();
    	~CEventNodeThreader();
    
    	bool process(CEventList *owner);
    private:
    	CThread *thread;
    	
    };
    
    
    // event/object managers will 
    // inherit this as base class
    class CEventList  {
    public:
    	CEventList();
    	~CEventList();
    
    public:
    	void add( CEventNode *e );
    	void empty(bool really);
    	void ignore();
    	void remove( long int id );
    	void setOwner(CThread *owner);
    	void spawnThread(CThread *thread);
    	
    	int size();
    	bool handle();
    
    private:
    	CThread *owner; 
    	CEventNode *head;
    	CEventNode *tail;
    	bool ignoreEvents;
    };
    
    // not the traditional thread in multithreading
    // but more along teh lines of a guide line strand.... right.
    class CThread {
    public:
    	CThread();
    	~CThread();
    
    	bool Run();
    	void setProcedure(CThread *thread); // sets a procedure
    	void removeProcedure();
    protected:
    	CThread * pActiveProcedure;
    	CEventList list;
    public:
    	char * name;
    };
    
    #else
    #endif
    UI: Header file
    [code]
    ///////////////////////////
    // UI.h
    // user interface header file
    #ifndef PR_UI
    #define PR_UI

    #include "global.h"
    #include "font.h"
    // The functionality of the User Interface is such that
    // at runtime the main windows thread spawns our top level
    // menu. This top level menu is a UIMain object, that spawns it's own thread
    // at this point the main window loop is waiting for this thread to return(finish)
    // The menu is a running thread with a list of events that need to be processed before
    // it can return to the main window loop and thus exit the application.
    // the list contains UIMenuItem objects that inherit EventNode, the list is cycled through
    // and the menu item performs as defined, some items might actually call for a new UIMenu
    // to spawn create a sub menu - at this point the winmain thread is waiting for the Main menu,
    // witch is now waiting on the submenu, the submenu then has it's own event list that needs to
    // be processed before it returns. Generally an Exit menu item will be the trigger to end the
    // event list and collapse back into teh calling thread. A UIMenuItem will also be capable of
    // spawning a GameThreadEvent witch up can return to the calling menu several methods - manual
    // escape, winning or losing - etc.

    class UIMenuItem;

    class UIMain : public CThread {
    public:
    UIMain();
    ~UIMain();

    void addItem(UIMenuItem *item);
    // thread process info

    private:
    // uhhhhhhh stuff
    };



    // UIMenuItem is an abstract interface for menu items
    // that range from strings, to media items
    // menu items actually decide if they are being
    // interacted with by the user rather then the menu
    // manager class doing so.
    class UIMenuItem : public CEventNode {
    public:
    UIMenuItem();
    ~UIMenuItem();
    // rather then obtain this global information manualy in each function,
    // a interface method is being implimented in case at some future point
    // i want this info obtain through strict process by authorized class managers
    // this saves time for redoing the process in teh long run.
    sKey getKey(int key); // checks global key structure for key activity
    sMouse getMouse(); // grab mouse info from global structure

    void setColor(float r, float g, float b);
    void setPos(int x, int y);
    void setSpawnEvent(CEventNode *e);
    bool hotSpot(int textx, int testy);

    protected:
    // uhhh other stuff
    CEventNode * spawn; // an event that spawns as a result of this thing being handled
    int x, y; // screen position;
    int width, height;
    sRGB color;
    };


    // UIItemStaticText
    // simple text lables
    class UIItemStaticText : public UIMenuItem {
    public:
    UIItemStaticText();
    ~UIItemStaticText();
    bool process(CEventList *owner);

    public:
    void setFont(char *name, int size);
    void setString(char *string);
    protected:
    char *string;
    GLFONT *pFont;
    };

    // UIItemTextOption
    // text item that interacts with user
    class UIItemTextOption : public UIItemStaticText {
    public:
    UIItemTextOption();
    ~UIItemTextOption();
    bool process(CEventList *owner);

    void setInteractColors(sRGB base, sRGB hightlight, sRGB down);
    private:
    sRGB highlightColor;
    sRGB downColor;

    };

    #else

    #endif
    [/quote]

    UI: function definitions
    Code:
    #include "global.h"
    
    UIMain::UIMain() {};
    UIMain::~UIMain() {};
    
    void UIMain::addItem(UIMenuItem *item) {
    	list.add(item);
    };
    
    	// thread process info
    
    UIMenuItem::UIMenuItem() { 
    	this->spawn=0; // nothing by default
    };
    
    void UIMenuItem::setSpawnEvent(CEventNode *e) {
    	this->spawn = e; // set an event to be triggered.
    };
    
    UIMenuItem::~UIMenuItem() { };
    
    sKey UIMenuItem::getKey(int key) {
    	// this needs protection data entry in place
    	// actually at this point its only read data
    	// should be protected when writing
    	return keys[key];
    };
    
    sMouse UIMenuItem::getMouse() {
    	// read data
    	return mouse; // this needs protection data entry in place
    };
    
    // set render position top left of an item
    void UIMenuItem::setPos(int x, int y) {
    	this->x = x;
    	this->y = y;
    };
    
    // set the color option
    void UIMenuItem::setColor(float r, float g, float b) {
    	this->color.r = r;
    	this->color.g = g;
    	this->color.b = b;
    };
    
    // test a pixel position against rectangle hotspot
    bool UIMenuItem::hotSpot(int testx, int testy) {
    	if(testx > x && testx < x+width) 
    		if(testy > y && testy < y+height)
    			return true;
    	return false;
    };
    // constructor for static text items
    // defaults to arial, size 14, "Menu Item" color black
    UIItemStaticText::UIItemStaticText() {
    	string = "Menu Item";	
    	this->pFont = new GLFONT("Arial", 14);
    	this->height = 14;
    	this->x = 20;
    	this->y = 20;
    	sRGB c = { 0, 0, 0 };
    	this->color = c;
    	this->width = pFont->stringWidth(string); // calculate size of default
    };
    
    UIItemStaticText::~UIItemStaticText() {
    	
    };
    
    // Static text is kind of a "permanent" event.
    // such that it is never handled and removed from the list
    // for this reason in order to exit from any thread that
    // contains a permanent event, a special exit event must
    // be spawned and processed in order to tell the thread to
    // forcefully empty it's event list and return true;
    bool UIItemStaticText::process(CEventList *owner) {
    	glColor3f(color.r, color.g, color.b);
    	pFont->display(x, y, string);
    	return false;
    };
    
    // set the font and size of static text item
    void UIItemStaticText::setFont(char *name, int size) {
    	this->pFont = new GLFONT(name, size);
    	this->height = size;
    	this->width = pFont->stringWidth(string); // calculate size of new font
    };
    // set teh string, of text.
    void UIItemStaticText::setString(char* string) {
    	this->string = string;
    	this->width = pFont->stringWidth(string); // calculate size of new string
    
    };
    
    
    // set default highlight and down colors
    // initialize default string and font
    UIItemTextOption::UIItemTextOption() {
    	sRGB h = { 1.0f, 0.0f, 0.0f }; // default highlight color is red
    	this->highlightColor = h;
    	sRGB d = { 1.0f, 1.0f, 0.0f };
    	this->downColor = d;
    };
    
    UIItemTextOption::~UIItemTextOption() {
    
    };
    
    // set colors for the text options, unfocused, focused and down
    void UIItemTextOption::setInteractColors(sRGB base, sRGB highlight, sRGB down) {
    	this->highlightColor = highlight;
    	this->downColor = down;
    	this->color = base;
    };
    
    bool UIItemTextOption::process(CEventList *owner) {
    	sMouse mpos = getMouse();
    
    	font->display(this->x - 30, this->y, "width: %i", width);
    	font->display(this->x + width, this->y, "|<- end|");
    	font->display(10.0f, 30.0f, "MB: %i, Mx: %i, My: %i, RECT(%i, %i, %i, %i)", mpos.button, mpos.x, mpos.y, this->x, this->y, this->x+this->width, this->y+this->height);
    	
    	if(this->hotSpot(mpos.x, mpos.y+this->height)) { // option have focus?
    		glColor3f(this->highlightColor.r, this->highlightColor.g, this->highlightColor.b);
    		if(!this->hotSpot(mpos.prevx, mpos.prevy))  // fist time having focus?
    		{
    			//ADDME: play mouse over sound
    			
    		}
    		if(mpos.button == 1) {
    			glColor3f(this->downColor.r, this->downColor.g, this->downColor.b);
    			//ADDME: play mouse over sound
    			//ADDME: spawn some event
    			if(this->thread != 0) // if there is a thread to spawn
    				owner->spawnThread(this->thread); // tell the list to spawn this thread
    			if(this->spawn != 0) // if there is an event to spawn
    				owner->add(this->spawn); // tell the list to spawn this event
    			pFont->display(x, y, string);
    			return false;
    		}
    		pFont->display(x, y, string);
    	} else { // option does not have focus
    		glColor3f(color.r, color.g, color.b);
    		pFont->display(x, y, string);	
    	}
    	return false;
    };
    And actually using the UI in the Initialize()
    Code:
    	// menu / process testing
    	MainMenu = new UIMain();
    	MainMenu->name = "Main Menu";
    
    	// make a menu item
    	// set properties
    	UIItemStaticText *item = new UIItemStaticText();
    	item->setString("Hyperspace 2005");
    	item->setFont("Times New Roman", 20);
    	item->setColor(0.25f, 0.50f, 0.75f);
    	item->setPos(g_winWidth/2, g_winHeight/2);
    	// add it to the menu
    	MainMenu->addItem(item);
    	
    	UIItemTextOption *item2 = new UIItemTextOption();
    	item2->setString("Start A New Game");
    	//item2->setInteractColors();
    	item2->setFont("Verdana", 20);
    	item2->setPos(g_winWidth/2, (g_winHeight/2)+22);
    	// add it to teh menu
    	MainMenu->addItem(item2);
    
    	item2 = new UIItemTextOption();
    	item2->setString("Another menu item.");
    	item2->setFont("Arial", 20);
    	item2->setPos(g_winWidth/2, (g_winHeight/2)+44);
    	MainMenu->addItem(item2);
    
    	UIItemTextOption *exit = new UIItemTextOption();
    	exit->setString("Exit");
    	exit->setFont("Arial", 18);
    	exit->setColor(0.01f, 0.01f, 0.8f);
    	exit->setPos(g_winWidth/2, (g_winHeight/2)+66);
    	exit->setSpawnEvent(new ListCleanUp(1));
    	MainMenu->addItem(exit);
    
    	// Sub menu test
    	UIMain *subMenu = new UIMain();
    	subMenu->name = "Sub Menu";
    	UIItemStaticText *subitem = new UIItemStaticText();
    	subitem->setString("This is a submenu!");
    	subitem->setFont("Times New Roman", 18);
    	subitem->setPos(g_winWidth/2, (g_winHeight/2));
    	subMenu->addItem(subitem);
    
    	UIItemTextOption *subitem2 = new UIItemTextOption();
    	subitem2->setString("Exit");
    	subitem2->setColor(0.3f, 0.9f, 0.4f);
    	subitem2->setPos(g_winWidth/2, (g_winHeight/2)+22);
    	subitem2->setFont("Sans Sarif", 20);
    	subitem2->setSpawnEvent(new ListCleanUp(0));
    	subMenu->addItem(subitem2);
    	// assign sub menu, to a button in main menu
    	item2->setThread(subMenu);
    
    
    	// officially associate the main menu as the primary game thread
    	GameThread = MainMenu; // set the game thread pointer to teh MAIN Menu
    c++->visualc++->directx->opengl->c++;
    (it should be realized my posts are all in a light hearted manner. And should not be taken offense to.)

  9. #9
    mov.w #$1337,D0 Jeremy G's Avatar
    Join Date
    Nov 2001
    Posts
    704
    OH FYI: This UI is used in the program in this thread: http://cboard.cprogramming.com/showthread.php?t=70368
    c++->visualc++->directx->opengl->c++;
    (it should be realized my posts are all in a light hearted manner. And should not be taken offense to.)

  10. #10

    Join Date
    May 2005
    Posts
    1,042
    Quote Originally Posted by SSJMetroid
    Hmmm, it's a good thought, but I wasn't really intending to use "Windows API." :P

    Never intended for it to be made fast. XD
    Well why didn't you specify this in the original post?
    I'm not immature, I'm refined in the opposite direction.

  11. #11
    Registered User SSJMetroid's Avatar
    Join Date
    Dec 2005
    Posts
    12
    My bad. ^^;;;

    [Edit:]
    Btw: Thanks for that UI example, Jeremy. That's sorta the kind of example I needed. You rock, dude.
    Last edited by SSJMetroid; 12-07-2005 at 02:13 PM.

  12. #12
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Windows is GUI hell, not GUI heaven.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. on method pointers and inheritance
    By BrownB in forum C++ Programming
    Replies: 2
    Last Post: 03-02-2009, 07:50 PM
  2. stuck on display method
    By shintaro in forum C++ Programming
    Replies: 2
    Last Post: 02-01-2009, 05:17 PM
  3. Best communication method to thousand childs?
    By Ironic in forum C Programming
    Replies: 8
    Last Post: 11-08-2008, 12:30 AM
  4. C# method
    By siten0308 in forum C# Programming
    Replies: 6
    Last Post: 07-15-2008, 07:01 AM
  5. Overriding a method in C
    By DavidDobson in forum C Programming
    Replies: 1
    Last Post: 07-05-2008, 07:51 AM