Cafu Engine
TypeSys Variables Overview

The "variable" classes in cf::TypeSys are supposed to turn a "normal" member variable of a class into something "more" that also other code can work with.

Problem and Motivation

In Cafu we use "components" to compose map entities and GUI windows, see the cf::GuiSys::ComponentBaseT hierarchy for an example. Components are classes like any other, but their member variables should be:

  • editable in our graphical map and GUI editor CaWE,
  • accessible via scripting, and
  • easy to serialize and deserialize (maps, GUIs, prefabs).

However, none of these features should impact the component in its actual, inherent purpose, being a component. The cf::GuiSys::ComponentBaseT classes should not be hindered in their performance, and their interfaces and implementations should not be cluttered with the details of the above requirements. In fact, it would be desireable to separate these issues from the components, so that the way in which the editors let users edit the variables or the details in which variables are bound to scripts can be varied without ever affecting the components themselves.

How it works

Consider the typical code structure of a component that has a member variable x:

class SomeComponentT
// [ other methods ... ]
void SetX(int newX);
int GetX() const;
int x;

A member variable usually implies three items: the variable itself, a "Get" function and a "Set" function. The implementations of the two functions are often trivial and inline, but it is not unusual that especially the "Set" function has side-effects, such as updating a graphical resource if a new filename has been set, etc.

Now, the key idea is to replace the variable and its Get/Set functions with a "wrapper" class. This is what the cf::TypeSys::VarT classes in this file are for.

As we also need a list of all cf::TypeSys::VarT instances in the class that contains them (the component), the cf::TypeSys::VarT classes all must derive from a common base class, cf::TypeSys::VarBaseT. As the list of variables should actually have more features than a plain array or list, we manage them in a cf::TypeSys::VarManT instance.

Finally, we apply the Visitor pattern to the cf::TypeSys::VarBaseT hierarchy: It allows user code to add arbitrary operations to the cf::TypeSys::VarBaseT instances without modifying them.