Sign in to follow this  
ajm113

Storing Objects With The Same Base Class In Vector

Recommended Posts

ajm113    355

I know this may seem like a very obvious question, but I want to be sure I'm approaching this situation correctly, or if I'm doing it wrong and there is a better picture I'm not simply seeing. I'm designing a GUI system for my game engine, since I just need a few controls and I don't need a fancy GUI library with all the bells and whistles. (Buttons, text, console, edit bar, images) So nothing fancy really. I wanted to know since I want to keep "pages" of the GUI. So if the user clicks "Credits" or "New Game" The UI will show another page with UI controls. Pretty simple stuff. Here is what I have already.

#ifndef GUI_MODEL_H
#define GUI_MODEL_H

#include "Vector.h"

enum GUI_STATE
{
	STATE_NULL = 0,
	STATE_CLICKED,
	STATE_HOVER,
	STATE_ACTIVE
};

class GUI_Model
{
public:
	GUI_Model(void);
	virtual ~GUI_Model(void);

	void setPosition(Vector<int> pos);
	void setSize(Vector<int> size);
	void setTexture(GLuint texture);
	void setDraw(bool draw);
	void enable(bool enable=true);

	virtual bool pointInside(Vector<int> pos);

	void setState(GUI_STATE state=STATE_NULL);
	GUI_STATE getState(void);


	virtual void draw(void) { return; };

protected:

	Vector<int>     m_position;
	Vector<int>     m_size;
	bool		m_enabled;
	bool		m_draw;
	GLuint		m_texture;
	GUI_STATE       m_state;

};

#endif

Which can work like this...

#ifndef BUTTON_H
#define BUTTON_H

class Button : public GUI_Model
{
     Button(std::string text);
     ~Button(void);

void  draw(void);

protected:
private:

//Custom params. Font, text, etc..
std::string text;
}

#endif

How I would like to see it work in a nutshell...

std::vector<std::vector<GUI_Model*>> pages;

//New Page
pages.push_back(std::vector<GUI_Model*>);
size_t current_page = 0;

Button* myButton = new Button("Click Me!");

myButton->setSize(Vector<int>(100, 30));

std::vector<std::vector<GUI_Model*>>
pages.at(current_page).push_back(myButton);


//Check button states handler / OpenGL calls, etc..
size_t num_pages = pages.size();
for(size_t i = 0; i<num_pages; i++)
{
    //etc....
}

I plan on using Game Monkey Script to create the UI for everything, so the code has to be very adaptable.

Edited by ajm113

Share this post


Link to post
Share on other sites
ajm113    355

What's the question?

 

The question is how can I write a vector or array to store mutliple class types that share the same sub class, while being able to store the data in the base class.

 

I.E

class Base
{
public:
Vector<int> size;
Vector<int> position;
};

class button : public Base
{
public:
std::string msg;
button_struct button_data;
};

class image: public Base
{
std::string imagePath;
}

//Some init funcs...

button m_button = new button("Click this");
image m_image = new image("image.png");

someVector.push_back(m_button);
someVector.push_back(m_image);

I was thinking of simply using how Win32 does things, and use the same architecture. (One class does all) and simple have a int that I can declare as what sort of object it is.

 

 

If you are looking for ideas and suggestions how to implement a GUI system, you should take a look at some of the existing ones to see how they approach these problems:

 

http://en.wikipedia.org/wiki/List_of_widget_toolkits

http://en.wikipedia.org/wiki/List_of_platform-independent_GUI_libraries

 

I'll take a look around, thank you for the post.

Edited by ajm113

Share this post


Link to post
Share on other sites
vstrakh    2455

There's no way you can store different classes in same vector.

You can store pointers to base class, leaving all type-dependent stuff hidden behind virtual methods.

Or you can wrap stored content of different type in some additional class, and explicitly check its type when you want to operate on exact stored class.

Share this post


Link to post
Share on other sites
TrianglesPCT    599

 The code seems pretty fishy to me, but at the very least replace this:

 

std::vector<std::vector<GUI_Model*>> pages

 

With:

 

std::vector<std::vector<std::unique_ptr<GUI_Model>>> pages

 

If you want to store these types by value in the container, and you have a known # of them, you can use boost:variant.

 

 

Share this post


Link to post
Share on other sites
Buckeye    10747


simply using how Win32 does things, and use the same architecture. (One class does all)

 

If that's the goal, then why code your own API? You can use CreateWindow(...) for various buttons and boxes and store the HWNDs in a vector. Specify BS_OWNERDRAW if you want to customize the look. Store an instance pointer and use GetWindowLongPtr to get the style and userdata for custom dispatching.

Share this post


Link to post
Share on other sites
Glass_Knife    8636

 


simply using how Win32 does things, and use the same architecture. (One class does all)

 

If that's the goal, then why code your own API? You can use CreateWindow(...) for various buttons and boxes and store the HWNDs in a vector. Specify BS_OWNERDRAW if you want to customize the look. Store an instance pointer and use GetWindowLongPtr to get the style and userdata for custom dispatching.

 

 

+1

 

Trying to make your own GUI API is going to be so much work that you're not actually going to get to use it.  Trying to handle the low-level operating system events while still keeping an abstraction for high-level code is not easy.  You would really be better off learning an existing API.  

Share this post


Link to post
Share on other sites
ajm113    355

 

 


simply using how Win32 does things, and use the same architecture. (One class does all)

 

If that's the goal, then why code your own API? You can use CreateWindow(...) for various buttons and boxes and store the HWNDs in a vector. Specify BS_OWNERDRAW if you want to customize the look. Store an instance pointer and use GetWindowLongPtr to get the style and userdata for custom dispatching.

 

 

+1

 

Trying to make your own GUI API is going to be so much work that you're not actually going to get to use it.  Trying to handle the low-level operating system events while still keeping an abstraction for high-level code is not easy.  You would really be better off learning an existing API.  

 

 

Well I guest that would depend on how complex we are talking about. If anything really the only things I would need to worry about IO is just the buttons. Everything else, images, text, are just for UI and not UE. Now if I was using scrollbars, dropdowns, the kitchen sink. I agree with you 100% and use CEGUI and save my self the trouble. In this case since I really just want buttons and nothing more for input. I dont think it's going to be that difficult. But thats just my point of view of the task. ;)

 

I just dont see why time and trouble needs to be spent using a library. (Easy to install at times vs writing your own code yes), but then having to ensure that lib works on targeted platforms, and licensing isnt going to be a issue down the road, specially if you just need to use 2% of the features the library includes.

 

 


simply using how Win32 does things, and use the same architecture. (One class does all)

 

If that's the goal, then why code your own API? You can use CreateWindow(...) for various buttons and boxes and store the HWNDs in a vector. Specify BS_OWNERDRAW if you want to customize the look. Store an instance pointer and use GetWindowLongPtr to get the style and userdata for custom dispatching.

 

 

I guest it wouldn't be a issue to make a base class that has everything needed, and just use uint to store params, now that you say it like that.

Edited by ajm113

Share this post


Link to post
Share on other sites
ajm113    355

I made a structure for anyone who maybe wondering how to setup a simple GUI system. As long as you know basic C++, some algebra, and English, it's pretty much filling the gaps...

 

This gui handler simply accepts the created model...

#ifndef GUI_HANDLER_H
#define GUI_HANDLER_H

#include "gui_model.h"

class gui_handler
{
public:
	gui_handler(void);
	virtual ~gui_handler(void);

	size_t newPage(void);
	bool insert(gui_model* model, size_t index=0);

	gui_model* poll_event(Vector<int> mouse, int state);

	void clearAll(void);
	

protected:
private:
	std::vector<std::vector<gui_model*>> m_pages;
};

#endif

This model simply stores extra params, and data about the control....

#ifndef GUI_MODEL_H
#define GUI_MODEL_H

#include "../Math/vector.h"

enum GUI_MODEL
{
	MODEL_NULL = 0,
	MODEL_BUTTON,
	MODEL_TEXT,
	MODEL_EDIT,
	MODEL_IMAGE
};

enum GUI_STATE
{
	STATE_NULL = 0,
	STATE_ACTIVE, //Used for edit field...
	STATE_RIGHT_CLICK_DOWN,
	STATE_RIGHT_CLICK_UP,
	STATE_LEFT_CLICK_DOWN,
	STATE_LEFT_CLICK_UP,
	STATE_HOVER,
	STATE_KEY_UP,
	STATE_KEY_DOWN
};

class gui_model
{
public:
	gui_model(GUI_MODEL model, std::string title, Vector<int> pos, Vector<int> size, bool draw = true, void* ptr = NULL);
	virtual ~gui_model(void);

	void show(bool draw=true);
	void setTitle(std::string title);
	void enable(bool enable = true);
	void setPosition(Vector<int> pos);
	void setSize(Vector<int> pos);
	void setTexture(GLuint tex=0);
	void setState(GUI_STATE=STATE_NULL);
	void setPtr(void* ptr);

	virtual void draw(void) { };
	virtual bool isInside(Vector<int> pos);

	GUI_MODEL	getModel(void);
	GUI_STATE	getState(void);
	bool		isEnabled(void);
	Vector<int> getPosition(void);
	Vector<int> getSize(void);
	void*		getPtr(void);

protected:
private:

	GUI_MODEL	m_model;
	GUI_STATE	m_state;

	std::string m_title;
	Vector<int> m_position;
	Vector<int> m_size;

	bool		m_draw;
	bool		m_enabled;
	GLuint		m_texture;
	void*		m_ptr;


};

#endif

Share this post


Link to post
Share on other sites
Khatharr    8812

 The code seems pretty fishy to me, but at the very least replace this:

 

std::vector<std::vector<GUI_Model*>> pages

 

With:

 

std::vector<std::vector<std::unique_ptr<GUI_Model>>> pages

 

If you want to store these types by value in the container, and you have a known # of them, you can use boost:variant.

 

 

 

My bad, man. I didn't mean to downvote that. There doesn't seem to be a way to undo it.

Edited by Khatharr

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this