Emergency 20 Dokumentation  4.2.0
CampClass.h File Reference
#include <camp/stringid.hpp>

Go to the source code of this file.

Classes

struct  camp::detail::QsfRawType< T, E >
 
struct  camp::detail::QsfRawType< const T >
 
struct  camp::detail::QsfRawType< T & >
 
struct  camp::detail::QsfRawType< T * >
 
struct  camp::detail::StaticTypeId< T >
 
struct  camp::detail::StaticTypeName< T >
 

Namespaces

 camp
 
 camp::detail
 

Macros

#define QSF_CAMP_RTTI()
 Only adds the virtual method "campClassId()", nothing more. More...
 
#define QSF_CAMP_TYPE(type)
 See "CAMP_TYPE" for details. More...
 
#define QSF_CAMP_TYPE_NONCOPYABLE(type)
 See "CAMP_TYPE_NONCOPYABLE" for details. More...
 
#define QSF_CAMP_ARRAY_INTERFACE_CLASS(interfaceClassName, ownerType, elementType)
 Define an CAMP array property wrapper for redirecting array requests into the C++ class interface which needs to perform additional work per request. More...
 
#define QSF_CAMP_ARRAY_INTERFACE_CLASS_WITH_VARIABLE(interfaceClassName, ownerType, variableType, elementType)
 
#define QSF_CAMP_ARRAY_PROPERTY(propertyName, ownerType, elementType)
 
#define QSF_CAMP_ARRAY_MAPPER_DEFINITION(interfaceClassName)
 

Functions

template<typename T >
uint32_t camp::detail::QsfStaticTypeId (const T &)
 
template<typename T >
const char * camp::detail::QsfStaticTypeName (const T &)
 

Macro Definition Documentation

#define QSF_CAMP_ARRAY_INTERFACE_CLASS (   interfaceClassName,
  ownerType,
  elementType 
)
Value:
class interfaceClassName \
{ \
public: \
typedef elementType ElementType; \
inline interfaceClassName(ownerType& owner) : mOwner(&owner) {} \
inline ownerType& getOwner() { return *mOwner; } \
inline const ownerType& getOwner() const { return *mOwner; } \
std::size_t size() const; \
const elementType& get(std::size_t index) const; \
void set(std::size_t index, const elementType& value); \
void insert(std::size_t before, const elementType& value); \
void remove(std::size_t index); \
private: \
ownerType* mOwner; \
};

Define an CAMP array property wrapper for redirecting array requests into the C++ class interface which needs to perform additional work per request.

Parameters
[in]propertyNameName of the CAMP array property to add to the given class, e.g. "Nodes"
[in]classNameName of the class without namespace to add the CAMP array property to, e.g. "NodesComponent"
Remarks
The CAMP reflection system supports arrays as class properties, but unlike elementary class properties it's no good idea to access those array properties by using getter and setter methods. This will lead to massive coping array instances around because returning array properties as references or pointers is not possible. For the compiler, a reference is a reference and no array.

The only decent way to access C++ arrays via the CAMP reflection system in general is to make the C++ array member variables public. In QSF, our convention is to declare CAMP metaclasses only inside "qsf::Plugin::onInstall()". In case you don't want to make the C++ array member variables public for the rest of the world while still being able to directly plugin the array property into CAMP without additional wrappers, it's valid to make your plugin class to a friend of the C++ class containing the array member variable. Please be warned that CAMP is now able to work without any security measurements directly on the array member variable. While this might be fine for several use-cases, there are situations were additional security checks or additional deferred work needs to be done as soon as there are changes inside the array. In case you're in such a situation, please continue reading, else you can stop reading right now and choose the simple direct approach.

Our solution is to add an C++ interface member variable which is used by a "camp_ext::ArrayMapper"-specialization in order to be able to let the CAMP reflection system interact with a certain C++ class interface. With this solution one is able to use the C++ class interface as usual and ignoring the CAMP reflection system if does not bring any benefit in certain use cases. On the other hand it's also possible to access an array by using the generic CAMP reflection system.

  1. The following example shows how to add an CAMP array property to your class. At first, use the "QSF_CAMP_ARRAY_PROPERTY()"-macro inside your C++ header below the "QSF_CAMP_RTTI()"-macro in order to define the CAMP array property:
    1 QSF_CAMP_RTTI() // Only adds the virtual method "campClassId()", nothing more
    2 QSF_CAMP_ARRAY_PROPERTY(Nodes, NodesComponent, glm::vec3) // Adds public member variable "Nodes" which is the middle part of the node array <-> CAMP interconnection
  2. Inside the initializer list of your class constructor, you need to initialize the automatically added public member variable by using "*this" as seen in the following example:
    1 NodesComponent::NodesComponent(Prototype* prototype) :
    2  Component(prototype),
    3  Nodes(*this), // Initialize the automatically added public member variable
  3. When declaring the CAMP metaclass, just declare our CAMP array property as you would do when connecting a public C++ class member variable directly to the CAMP reflection system:
    1 camp::Class::declare<NodesComponent>()
    2  .base<Component>()
    3  .property("Nodes", &NodesComponent::Nodes)
    4 );
    "NodesComponent::Nodes" is in fact the public C++ class member variable you defined above by using the "QSF_CAMP_ARRAY_PROPERTY()"-macro.
  4. Next implement the CAMP array property interface methods for the class implicitly defined by step 1:
    1 inline std::size_t NodesComponent::NodesInterface::size() const
    2 {
    3  return getOwner().getNodes().size();
    4 }
    5 inline const glm::vec3& NodesComponent::NodesInterface::get(std::size_t index) const
    6 {
    7  return getOwner().getNodes().at(index);
    8 }
    9 inline void NodesComponent::NodesInterface::set(std::size_t index, const glm::vec3& value)
    10 {
    11  getOwner().setNode(index, value);
    12 }
    13 inline void NodesComponent::NodesInterface::insert(std::size_t before, const glm::vec3& value)
    14 {
    15  getOwner().insertNode(before, value);
    16 }
    17 inline void NodesComponent::NodesInterface::remove(std::size_t index)
    18 {
    19  getOwner().removeNode(index);
    20 }
    You can do this either in your C++ source code file (not inlined then, of course), or when using simple wrapper methods like those in the sample code, inside your C++ class header or "-inl.h"-file in case you're using one.
  5. Finally, you need to tell the CAMP reflection system how to interact with the array by defining a CAMP array mapper class:
    1 QSF_CAMP_ARRAY_MAPPER_DEFINITION(qsf::NodesComponent::NodesInterface)
    Do this inside your C++ class header, outside of any namespaces, preferably at the end of the header file. For this to work without compiler errors, you will need to include the CAMP array mapper definition into the C++ class header as well:
    1 #include <camp/arraymapper.hpp>
#define QSF_CAMP_ARRAY_INTERFACE_CLASS_WITH_VARIABLE (   interfaceClassName,
  ownerType,
  variableType,
  elementType 
)
Value:
class interfaceClassName \
{ \
public: \
typedef elementType ElementType; \
inline interfaceClassName(ownerType& owner, variableType& variable) : mOwner(&owner), mVariable(&variable) {} \
inline ownerType& getOwner() { return *mOwner; } \
inline const ownerType& getOwner() const { return *mOwner; } \
inline variableType& getVariable() { return *mVariable; } \
inline const variableType& getVariable() const { return *mVariable; } \
std::size_t size() const; \
const elementType& get(std::size_t index) const; \
void set(std::size_t index, const elementType& value); \
void insert(std::size_t before, const elementType& value); \
void remove(std::size_t index); \
private: \
ownerType* mOwner; \
variableType* mVariable; \
};
#define QSF_CAMP_ARRAY_MAPPER_DEFINITION (   interfaceClassName)
#define QSF_CAMP_ARRAY_PROPERTY (   propertyName,
  ownerType,
  elementType 
)
Value:
public: \
QSF_CAMP_ARRAY_INTERFACE_CLASS(propertyName##Interface, ownerType, elementType); \
propertyName##Interface propertyName; \
private:
#define QSF_CAMP_ARRAY_INTERFACE_CLASS(interfaceClassName, ownerType, elementType)
Define an CAMP array property wrapper for redirecting array requests into the C++ class interface whi...
Definition: CampClass.h:223
#define QSF_CAMP_RTTI ( )
Value:
public: virtual uint32_t campClassId() const {return camp::detail::QsfStaticTypeId(this);} \
public: virtual const char* campClassName() const {return camp::detail::QsfStaticTypeName(this);} \
private:
const char * QsfStaticTypeName(const T &)
Definition: CampClass.h:54
uint32_t QsfStaticTypeId(const T &)
Definition: CampClass.h:52

Only adds the virtual method "campClassId()", nothing more.

Note
  • See "CAMP_RTTI"-documentation for details.
  • From "camp/camptype.hpp" (names changed to avoid collisions)
#define QSF_CAMP_TYPE (   type)
Value:
namespace camp \
{ \
namespace detail \
{ \
template <> struct StaticTypeId<type> \
{ \
static uint32_t get(bool = true) {return StringId(#type);} \
enum {defined = true, copyable = true}; \
}; \
template <> struct StaticTypeName<type> \
{ \
static const char* get(bool = true) {return #type;} \
enum {defined = true, copyable = true}; \
}; \
} \
}
Definition: Main.h:42
Definition: Component.h:21

See "CAMP_TYPE" for details.

Note
  • From "camp/camptype.hpp" (names changed to avoid collisions)
#define QSF_CAMP_TYPE_NONCOPYABLE (   type)
Value:
namespace camp \
{ \
namespace detail \
{ \
template <> struct StaticTypeId<type> \
{ \
static uint32_t get(bool = true) {return StringId(#type);} \
enum {defined = true, copyable = false}; \
}; \
template <> struct StaticTypeName<type> \
{ \
static const char* get(bool = true) {return #type;} \
enum {defined = true, copyable = false}; \
}; \
} \
}
Definition: Main.h:42
Definition: Component.h:21

See "CAMP_TYPE_NONCOPYABLE" for details.

Note
  • From "camp/camptype.hpp" (names changed to avoid collisions)