Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

7 Neutral

About Geosesarma

  • Rank

Personal Information

  • Interests

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Geosesarma

    Console Menu Structure - How to get node type

    In the end the topic has some good thoughts and lots of code which might be helpfull for other people with similar design decisions. For my part I see the initial question solved. Nevertheless I am grateful for any help I have received so far !
  2. Geosesarma

    Console Menu Structure - How to get node type

    You can check out the composite pattern. Because MenuItem is the base class I have to use a pointer to the base class in order to store any "MenuItem" in it.... Sure you can forward declare your class and use a pointer. class B; class A { public: B* b; } class B { public: A* a; } Yes you are correct a SubmenuItem is a container for MenuItems but a SubmenuItem can also contain other SubmenuItems. Therefore it would (in my case) be pointless to not inherit from MenuItem. Especially with the type system in place.
  3. Geosesarma

    Console Menu Structure - How to get node type

    I probably just programmed the manual dynamic_cast version in the most cumbersome way possible but at least its a starting point for my brain to work with. Thanks anyway Acosix and of course all the others who helped me. (Not tested, no production code!) class MenuItem { private: size_t typeID; std::string name; static size_t generateID() { static size_t id; return id++; } public: MenuItem() : typeID(0), name("") {} template <typename T> static size_t getTypeID() { static size_t id = generateID(); return id; } void setName(const std::string& n) { name = n; } const std::string& getName() const { return name; } void setID(size_t id) { typeID = id; } size_t getID() { return typeID; } }; class ActionItem : public MenuItem { public: ActionItem(const std::string& displayName) { setName(displayName); setID(MenuItem::getTypeID<ActionItem>()); } }; class SubmenuItem : public MenuItem { private: std::vector<MenuItem*> childItems; MenuItem* findRec(const std::string& name, std::vector<MenuItem*>& childs) { for (auto& child : childs) { if (child->getName() == name) return child; if (child->getID() == MenuItem::getTypeID<SubmenuItem>()) { SubmenuItem* sub = static_cast<SubmenuItem*>(child); if (sub->childItems.size() <= 0) return nullptr; else return findRec(name, sub->childItems); } } return nullptr; } public: SubmenuItem(const std::string& displayName) { setName(displayName); setID(MenuItem::getTypeID<SubmenuItem>()); } template <typename T> T* get(const std::string& whatIwant) { MenuItem* temp = findRec(whatIwant, childItems); if (temp && temp->getID() == MenuItem::getTypeID<T>()) return static_cast<T*>(temp); else return nullptr; } void add(MenuItem * item) { childItems.push_back(item); } //Only for testing void print() { cout << "=====================================" << endl; cout << "childItems from -- " << getName() << " -- " << endl; cout << "=====================================" << endl; for (const auto& m : childItems) { cout << m->getName() << endl; } cout << "=====================================" << endl; } };
  4. Geosesarma

    Console Menu Structure - How to get node type

    Maybe I should be more precise in what I want to achieve. First things first: I´m only interessted in building the menu structure (no navigating or drawing logic). A SubmenuItem is just a container which contains other "MenuItems". A ActionItem is just a class, which triggers a function/an event. Another class, maybe MenuNavigator should be able to iterate through the Menu. It also should be able to keep the current state (current selected, current SubmenuItem ect). Navigation could look like this: Player presses arrow down: cursor gets one "MenuItem" down. Player presses arrow up: cursor gets one "MenuItem" up. Player presses X: if current selected MenuItem is a SubmenuItem set its childs as the current "Submenu", if current selected MenuItem is an ActionItem, trigger a function/ an event. It´s just a name which should be displayed (like the windows filesystem -> a folder(=SubmenuItem) has a name, a file(=ActionItem) has a name ) Maybe I should just store pointers from classes which I want to use in a "Menu" class and use them directly.
  5. Geosesarma

    Console Menu Structure - How to get node type

    First things first: Ofc you cant know it but the code I used in my example is just a quick "expression of my thoughts". I´m aware of possible memory leaks and that I should use smart pointers instead of raw pointers ^^ Maybe I do not quite understand your code or how it translates to my problem but I think it´s not far away from registering an enum or am unique identifier in the ctor of my classes and give me the right type back based on these "tags". On the other hand I could use your "Linked List approach" then I could say: A Submenu can have a parent (if its nullptr then I know I´m at the root level) AND a Submenu can have either a pointer to another Submenu OR a pointer to an ActionItem. Thus I only have to check which pointer is not a nullptr.
  6. Geosesarma

    Console Menu Structure - How to get node type

    You are absolutely right every intermediate node hast to be a submenu. But lets assume a Submenu S1 contains 2 Items: 1 ActionItem A2 and 1 Submenu S2. Both have the same parent (S1). But in this case S2 doesnt has any items....therefore I dont can trust the "is it an itermediate node check" or am I completly wrong? +-- S1 -- + -- S2 + -- A2
  7. Geosesarma

    Console Menu Structure - How to get node type

    Many thanks for you response! I typed the code into the code tags from gamdev...this code wasnt´t meant to be run into a real world application (only for demonstrating my problem) After some research I get the impression there is no real "solution". Either you use rtti (typeid, dynamic_cast ...) or you spin your own "manual" rtti system (or you save all concrete types into the submenu as you mentioned). The visitor pattern doesnt work for my problem either....sure I get the right type in my visitor implementations but how can I return the object(with the right type)? I also looked into two ECS implementations (GetComponent<T>()) and they always use some sort of "marker"(id, enum, string) to identify their component in a container and cast them with static_cast.
  8. Hi, I´m currently developing a little menu system for a console game. As a starting point I divided the Menu in three areas: the actual data structure, a navigation class which can navigate through the "tree" and holds the state (currently active SubMenu) and a class which draws the whole thing. In its simplest form I want it to behave/look like the following: 1) Every "Node" represents a MenuItem 1.1) Each MenuItem can either be a SubMenuItem or an ActionItem 1.2) Every SubMenu can contain 0 to N childs 2) If I navigate to a SubMenuItem and it has childs I want to display them. If I navigate to an ActionItem it should trigger a function. As a class hirarchy to actually build the menu I thought something like this would work: class MenuItem { public: virtual void action() = 0; virtual string& getItemName() = 0; } class ActionItem : public MenuItem { public: void action() override { //Trigger stuff } string& getItemName() { return itemName; } } class SubMenuItem : public MenuItem { private: vector<MenuItem*> childItems; public: void action() override { //What to do? } string& getItemName() { return itemName; } void add(MenuItem* m) {...} void rm(MenuItem* m) {...} MenuItem* find(const string& name) {...} } To create the menu I could then do this: SubMenuItem root, options; ActionItem exit, start, fullScreenMode, windowMode options.add(&fullScreenMode); options.add(&windowMode); root.add(&start); root.add(&options); root.add(&exit); // Should look like this +--start | +--options--+--fullScreenMode | +--windowMode +--exit But now I created myself a problem: How should I actually get the type of my MenuItem? Lets say I want to find the options SubMenu and add some ActionItems at runtime. In order to do this I can call find on the root object but then I only have a MenuItem pointer which can call action() or getItemName(). To get around this problem I could add some methods to my MenuItem interface, but I think that would be the wrong way (as you can see with the action method -> SubMenuItem has no real use for it). Another solution could be the use of dynamic_cast but wouldn´t it be a sign of a bad design? MenuItem* options = root.find("options"); options. ??? //Fix? class MenuItem { public: virtual void action() = 0; virtual string& getItemName() = 0; virtual bool isSubmenu() = 0; virtual vector<MenuItem*> getChild() = 0; } MenuItem* options = root.find("options"); if(options->isSubmenu()) options->getChild().push_back(new ActionItem()); //Or maybe this? SubMenuItem* options = dynamic_cast<SubMenuItem*>(root.find("options")); if(options) options->add(new ActionItem()) Am I on the right track or is this complete bs? Should I use templates (CRTP) for this kind of problem or is maybe the visitor pattern a good match for this problem? I hope you understand my problem can can give me some hints!
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!