Hi Peter, I'm open to suggestions on making the implementation more flexible, however, any extra complexity has to be strongly justified - i.e. with concrete usage case, so could you flesh out what you'd want to do with the subclassing from UserDataContainer.
Another route for adding extra flexiblity would be to just subclass your own user data scheme from osg::Object and assign it as UserData or as UserObject, then do a dynamic cast to get access to your custom implementation. Currenly you can share UserData and UserObjects between their owner osg::Object. As for sharing whole UserDataContainer objects between their owner osg::Objects, this is something I considered and implemented initially but then decided to make things simpler and just have an internal data container subclassed from osg::Referenced. Adding the capability of sharing UserDataContainer won't be difficult, but will require us to push the declaration of the UserDataContainer into the public scope something that will constain how flexibile we can be with the implementation and it's interface, and would require us to implement UserDataContainer as an osg::Object rather than Referenced so we could get the cloning support that osg::Object provides. A subclassable UserDataContainer would also push us towards subclassing from osg::Object, which isn't difficult, but it does open the doors users nesting UserDataContainer within a UserDataContainer, now this could be seen as an advantage or just extra complexity. Initially I implemented UserDataContainer as a subclass from osg::Object but then pulled back as the public interface for access to the internal UserDataContainer conflicted with the UserDataContainer's own access functions - I had to make the osg::Object methods virtual and override then in UserDataContainer and it ended up being rather messy. The other issue that a subclassable UserDataContainer brings is that what happens during serialization - when we writing out we could use the standard UserDataContainer access methods, but when reading back in you'd want to construct explitly the custom UserDataContainer for each node than needs it. You can probably solve this by serializng the UserDataContainer itself, and have a custom wrapper to implement the CustomUserDataContainer so that the serializer creates everything appropriately. This is fine but it leaves the question of how to map the old UserData and Description list in a backwards compatible way. For now I am going to get the serializers working for .osgb/.osgt,/osgx as they are and if that all works I'll check my work in so that others can test the build and runtime side. Once we have the simplicist implementation working fine we'll be able to a base for concrete proposals for adding even greater flexibility, but be prepared to fight your corner if the extra flexibility comes with extra complexity ;-) Robert. On Tue, May 31, 2011 at 5:36 PM, Peter Amstutz <peter.amst...@tseboston.com> wrote: > Hi Robert, > > This looks pretty straightforward and I agree that less complexity is > good. However a would modify it slightly to support two related > features I have been lobbying for, which are the ability to share > UserDataContainers between osg::Objects, and the ability to subclass a > custom UserDataContainer implementation. > > The idea is that there is generally not a 1:1 correlation between the > application entity model and the scene graph. Because of this, one > often wants to be able to share or inherit metadata information, or look > up metadata on the fly to avoid copying large amounts of application > data into the scene graph. > > I think it feasible to add one level of indirection without adding too > much complexity. For example: > > - Make osg::UserDataContainer a pure abstract class. > > class OSG_EXPORT UserDataContainer : public osg::Referenced > { > public: > void addUserObject(Object* owner, Object* obj) = 0; > void setUserObject(Object* owner, unsigned int i, Object* obj) = 0; > void removeUserObject(Object* owner, unsigned int i); > > unsigned int getUserObjectIndex(Object* owner, const osg::Object* obj) > const = 0; > unsigned int getUserObjectIndex(Object* owner, const std::string& > name) const = 0; > > Object* getUserObject(Object* owner, unsigned int i) = 0; > const Object* getUserObject(Object* owner, unsigned int i) const = 0; > > Object* getUserObject(Object* owner, const std::string& name) = 0; > const Object* getUserObject(Object* owner, const std::string& name) > const = 0; > > unsigned int getNumUserObjects(Object* owner) const = 0; > > }; > > - Provide a default implementation which doesn't do anything with the "owner" > field > class OSG_EXPORT DefaultUserDataContainer : public UserDataContainer > { > ref_ptr<Referenced> _userData; > b DescriptionList _descriptionList; > ObjectList _objectList; > public: > void addUserObject(Object* owner, Object* obj) { > _objectList.push_back(obj); > } > /* etc */ > }; > > > - The methods implementated in osg::Object just forward to the container > along with the owner: > > void osg::Object::addUserObject(Object* obj) { > if (!_container) { > _container = new osg::DefaultUserDataContainer(); > } > _container->addUserObject(this, obj); > } > > void osg::Object::setUserObject(Object* owner, unsigned int i, Object* > obj) { > if (!_container) { > _container = new osg::DefaultUserDataContainer(); > } > _container->setUserObject(this, i, obj); > } > > /* etc */ > > - osg::Object also gains a couple of new methods: > osg::UserDataContainer* osg::Object::getUserDataContainer(); > osg::Object::setUserDataContainer(osg::UserDataContainer*); > > > Does this seem reasonable? > > - Peter > > -- > Peter Amstutz > Senior Software Engineer > Technology Solutions Experts > Natick, MA > 02131 > > _______________________________________________ > osg-users mailing list > osg-users@lists.openscenegraph.org > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org > _______________________________________________ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org