Programming and other useless stuff: Data Inheritance made easy.

Monday, August 11, 2008

Data Inheritance made easy.

Yesterday I wrote that the basics for the templates seem to be finished. 'Seemed' is the right word :) In fact, while implementing the inheritance today, I figured out several things:

1. the ComponentTemplates don't need to know their owner. That information is only interesting for the component that actually wants to alter something to its owner.

2. Moving the ReferenceCounted Interface from the ComponentTemplates to the Templates is good :) In fact, the templates itself need the interface in order to be able to be referenced to within other interfaces. Some years ago I used reference counting all over the place for my projects. I dropped them when I was working for some clients and I thought that reference counting on my projects might be some kind of overkill. Nevertheless, the way the templates are used in my game make it necessary to ensure that any object is still available as long as another object is referencing to it. While smartpointers might sound interesting here, I did that my own small interface (just 2 functions) is enough for me.

3. Not cloning... initially I wanted to just hold a pointer to the source template (from which a template inherits), clone the component template and add those clones to the current template. But I decided to not handle the inheritance this way. Why would I want to clone some data that is available and that would not be altered at this point? Inheritance of data only means replacing a component of a given type with a component of the same type (but holding different data). Therefor the only point in the source code to alter would be the point where the new component is added.

Inheriting from a parent is as simple as this:

// The basic information about the template has been loaded by the above layer.
// That information has been used to actually create this object.
const TiXmlNode *srctemplate = _pElement->FirstChild("inherited");
if (srctemplate && ( TiXmlNode::ELEMENT == srctemplate->Type() ))
{
const TiXmlElement *element = static_cast(srctemplate);
const char* tempType = element->Attribute("name");
if ( NULL != tempType )
{
// We have to request the source template from the entitymanager.
m_inheritedFrom = EntityManager::Instance().getTemplate( tempType );
if ( NULL == m_inheritedFrom )
{
return false;
}

// We got the source template, we have to add the source components to the current template.
COMPONENTARRAY::iterator it = m_inheritedFrom->m_components.begin();
while ( it != m_inheritedFrom->m_components.end() )
{
addComponent( *it );
++it;
}
}
}


The addComponent code looks like this:

bool
EntityTemplate::addComponent(ComponentTemplate *_component)
{
if ( std::find(m_components.begin(), m_components.end(), _component ) != m_components.end() )
return false;

// Try to find a component of the same type.
COMPONENTARRAY::iterator it = m_components.begin();
while ( it != m_components.end() )
{
// It's the same type.
if ( (*it)->getType() == _component->getType() )
{
// Set the new one.
m_components.insert(it, _component);
_component->addRef();

// Release the old one.
(*it)->release();
m_components.erase(it);

return true;
}
++it;
}

m_components.push_back(_component);
_component->addRef();
return true;
}


Nothing more is needed for inheritance from one parent to another. In the XML code, it looks like this:







Inheritance is always resolved before the actual component template loading. Thus the overloading magically happens without any problems :)

As I said: Data Inheritance made easy.

Have fun,
Stefan

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home