mosra / magnum

Lightweight and modular C++11 graphics middleware for games and data visualization
https://magnum.graphics/
Other
4.76k stars 439 forks source link

Easier access to scenegraph object's features #395

Open pezcode opened 4 years ago

pezcode commented 4 years ago

It would be nice to have utility functions on SceneGraph::Object to find attached features by type, similar to e.g. Unity's components.

object.features(); // list of AbstractFeatures&
object.feature<Drawable>(); // Drawable* or nullptr
object.features<Drawable>(); // list of Drawable&
object.featuresInChildren<Drawable>();
object.featuresInParents<Drawable>();
Squareys commented 4 years ago

Heh, I actually have exactly this in a project of mine:

        /**
         * @brief Get first feature with specified type
         * @return the feature or @cpp nullptr @ce if this object had no
         * such feature attached to it.
         */
        template<typename T>
        T* feature() {
            for(auto& f : this->features()) {
                if(T* feat = dynamic_cast<T*>(&f)) {
                    return feat;
                }
            }

            return nullptr;
        }

I'll also note here, that I have a very rough implementation for an pre-order iterator on a SceneGraph hierarchy, in case someone needs something like that.


Edit:

Oh, and welcome to Magnum! Just noticed this is your first issue here, how rude of me 😅

mosra commented 4 years ago

This is a good idea! :+1:

As @Squareys says, it would probably need to rely on RTTI to be generic enough. I need to think how to easily return a list without having to allocate something (if that's even possible) -- storing features ordered by type could possibly work.

Btw., an alternative to magnum's scenegraph, which was designed in a quite OOPy sense back in the day, could be EnTT. You're encouraged to try both and pick the one that suits you better. Some examples, courtesy of @alanjfs: https://gist.github.com/alanjfs

pezcode commented 4 years ago

@Squareys Thanks! My code looks about the same. Did you subclass Object for this? I gave that a try but got annoyed at having to cast to my derived type quite a bit, e.g. from parent().

@mosra I don't see a way around RTTI, either. Allocations are probably necessary if you don't want to start adding unique tags to features to be able to sort them.

It was really helpful to have a usable scenegraph coming with Magnum already. Having drawables and animables is just about enough for my use case but I might take another look at an entity system later, thanks for the pointer.