Kigs Framework Introduction (3/8) - Attributes






3.48/5 (6 votes)
A multi-purpose, cross-platform, free and Open Source C++ framework. This article will focus on CoreModifiable attributes.
Table of Contents
- Introduction
- Declaration
- Types
- Dynamic Attributes
- Access
- Owner Notification
- Serialization
- Already Published in this Series
- History
Introduction
In the previous articles of this series (here and here), we overviewed the Kigs framework and detailed CoreModifiable
class.
This article will focus on CoreModifiable
attributes.
CoreModifiable
attributes can be seen as member variables you can access (getters/setters) by their name (given as a string), without knowing the runtime type of your instance (you can call getters/setters directly using a CoreModifiable
pointer).
They are also automatically serialized, and you can use reflexion to know if an attribute is available or get the list of attribute of an instance.
There are three main CoreModifiable
attributes:
- 'maType' attributes: like maInt
, maFloat
, maReference
... ('ma' prefix if for modifiable attribute), are specific types you can use to declare CoreModifiable
attribute member variables.
- mapped attributes: you declare classic member variables (int mIntValue = 0;) then you declare them as CoreModifiable
attributes using the WRAP_ATTRIBUTES
helper macro.
- dynamic attributes: you can add dynamic attribute (and remove it later, if it was added dynamically) to a CoreModifiable
instance, when you want only some specific instances (and not all the instances of the same class) to use this attribute or when the attribute is needed only temporarily.
Declaration
'maType' attributes
CoreModifiable
attributes can be defined at compile time as member variable of a CoreModifiable
or at runtime as dynamic attributes.
When defined as member variable, two definitions/declarations are possible:
Modern C++ Style
Using the helper macros BASE_ATTRIBUTE
:
// declare m_val member variable as a integer CoreModifiable attribute with
// name "IntValue" and with default value 12
maInt m_val=BASE_ATTRIBUTE(IntValue,12);
// declare m_fval member variable as a float 'Init' CoreModifiable attribute with
// name "FloatValue" and with default value -1.0f
// once owning instance is initialized, m_fval is read only ( init attribute )
maFloatInit m_fval=BASE_ATTRIBUTE(FloatValue,-1.0f);
Each 'maType' type has an associated 'maTypeInit' type indicating the attribute is needed to initialize the CoreModifiable
. Once the CoreModifiable
initialized, an init attribute is set as read only.
Classic Constructor Init
In class declaration:
// declare m_val member variable as a integer CoreModifiable attribute
maInt m_val;
// declare m_fval member variable as a float 'Init' CoreModifiable attribute
maFloatInit m_fval;
In class constructor:
IMPLEMENT_CONSTRUCTOR(SimpleClass)
// attribute name and default value is given to the constructor
, m_val(*this,"IntValue",12)
// attribute name and default value is given to the constructor
, m_fval(* this, "FloatValue",-1.0f)
{
}
Owning Class Access
The owning class can often use 'maType' CoreModifiable
attributes directly like a classic member variable :
// change m_val value
// (read only is not used when direct access is done)
m_val+=5;
// use m_val directly without getValue
float result = 5+m_val;
Mapped attributes
It is also possible to map CoreModifiable
attributes on existing member variables using the WRAP_ATTRIBUTES
macro.
// declare and init member variables
std::string mStringMemberVariable="a text";
u32 mUIntMemberVariable = 50;
// indicates mStringMemberVariable and mUIntMemberVariable are CoreModifiable attributes that can be access using
// "StringMemberVariable" and "UIntMemberVariable" names
// the variables will also be serialized when exporting/importing the instance.
WRAP_ATTRIBUTES(mStringMemberVariable,mUIntMemberVariable);
Types
Basic Types
Numeric Types
maChar
: manage signed 8 bits integermaShort
: manage signed 16 bits integermaInt
: manage signed 32 bits integermaLong
: manage signed 64 bits integermaUChar
: manage unsigned 8 bits integermaUShort
: manage unsigned 16 bits integermaUInt
: manage unsigned 32 bits integermaULong
: manage unsigned 64 bits integermaFloat
: manage float valuemaDouble
: manage double value
String Types
maString
: managestd::string
valuemaUSString
: manage UTF16 string value
Other Basic Types
maBool
: manage bool valuemaEnum
: manage an énumération.maEmum
needs template parameter for the possible enumeration value count. Here is an example ofmaEnum
declaration:
// m_RequestType enum can take values "GET", "POST", "PUT", "DELETE"
maEnum<4> m_RequestType = BASE_ATTRIBUTE(Type, "GET", "POST", "PUT", "DELETE");
Advanced Types
Array / Vector Types
maVect2DF
: manage 2d floating point value vectormaVect2DI
: manage 2d integer (32 bits) value vectormaVect3DF
: manage 3d floating point value vectormaVect3DI
: manage 3d integer (32 bits) value vectormaVect4DF
: manage 4d floating point value vectormaVect16DF
: manage 16 floating point value vector ( <=> 4x4 matrix )maMatrix22DF
: manage 2x2 floating point matrixmaMatrix33DF
: manage 3x3 floating point matrix
Reference
maReference
: manage a reference on aCoreModifiable
instance.
A reference is generally initialized with a string giving a path to the wanted instance. Basic path can have this form:
"classtype:classname
".
maReference
does not change reference counting of the referenced object.
Owning class can retrieve pointer on the referenced instance with a cast on CoreModifiable
:
CoreModifiable* other = (CoreModifiable*)m_Ref;
getValue
can also be used:
CMSP other;
instance->getValue("Reference",other);
Raw Buffer
maBuffer
: manage raw data (binary) buffer
CoreItem
maCoreItem
: manage JSon style object structures
CoreItem
class is detailed in a next article.
Computed Numeric Parameter
maComputedNumeric
: call given methods onCoreModifiable
owner instance to compute parameter whengetValue
orsetValue
are called. The parameter is not stored but recomputed at each call.
Dynamic Attributes
Attributes can be added to an instance at runtime:
instance2->AddDynamicAttribute
(CoreModifiable::ATTRIBUTE_TYPE::STRING, "DynamicAttribute", "initValue");
AddDynamicAttribute(CoreModifiable::ATTRIBUTE_TYPE::UINT, "DynamicAttribute", 1250);
and then accessed like other attributes (as described in the next section).
Of course, dynamic attributes can also be removed:
// remove "DynamicAttribute" from this
RemoveDynamicAttribute("DynamicAttribute");
Access
CoreModifiable
attributes can be accessed by their names using setValue
and getValue
methods on owning instance like this:
instance->setValue("IntValue", 16);
// retrieve value using templated "getValue" method
int v = instance->getValue<int>("IntValue");
// or with reference parameter
int v1;
if(!instance->getValue("IntValue",v1))
{
// instance does not own "IntValue" parameter
}
Array Access
vector
and matrix
can be accessed using getValue
and setValue
:
// accessing vector
v4f vect;
instance1->getValue("Vector", vect);
std::cout << "vector values : [" << vect.x << "," << vect.y << ","
<< vect.z << "," << vect.w << "]" << std::endl;
// set value with string
instance1->setValue("Vector", "[2.0,1.0,0.0,-1.0]");
or with setArrayValue
/ getArrayValue
:
// access with array of values
float arrayv[4];
instance1->getArrayValue("Vector", arrayv, 4);
std::cout << "vector values : [" << arrayv[0] << "," << arrayv[1] << ","
<< arrayv[2] << "," << arrayv[3] << "]" << std::endl;
arrayv[2] = 10.0f;
instance1->setArrayValue("Vector", arrayv,4);
or for a given element with getArrayElementValue
/ setArrayElementValue
:
// by element
instance1->getArrayElementValue("Vector", arrayv[0], 0,2);
std::cout << "vector values : [" << arrayv[0] << "," << arrayv[1] << ","
<< arrayv[2] << "," << arrayv[3] << "]" << std::endl;
Owner Notification
The owner of an attribute can ask to be notified when a setValue
is called on this attribute:
// NotifyUpdate method will be called when a setValue occur on "StringValue"
setOwnerNotification("StringValue",true);
The owner class should override NotifyUpdate
method to receive the notification:
void SimpleClass::NotifyUpdate(const u32 labelid)
{
if (labelid == KigsID("StringValue")._id)
{
std::cout << "StringValue new value is : " << m_StringValue << std::endl;
}
}
Serialization
In XML files, attributes are defined like this for class attributes:
<Attr N="IntValue" V="10"/>
or like this for dynamic attributes:
<Attr N="FloatValue" T="float" V="5.5" Dyn="yes"/>
The initial value can be set directly in V
tag like above, or be evaluated from an expression like this:
<Attr N="FloatValue" V="eval(32.4*4.2)"/>
More complex expressions are possible and are explained in the article about CoreItem
.
Find all the sample code from this article in Sample3 project (browse the code).
Already Published in this Series
- Kigs Framework Introduction (1/8) - Overview
- Kigs Framework Introduction (2/8) - CoreModifiable
- Kigs Framework Introduction (3/8) - Attributes
- Kigs Framework Introduction (4/8) - Methods
- Kigs Framework Introduction (5/8) - CoreItem
- Kigs Framework Introduction (6/8) - Signal, Slot, Notification
- Kigs Framework Introduction (7/8) - Lua Binding
- Kigs Framework Introduction (8/8) - Data Driven Application
History
- 7th February, 2020: Initial version
- 14th February, 2020: Article (4/8) added to the series
- 21st February, 2020: Article (5/8) added to the series and small bug fix in code
- 2nd March, 2020: Article (6/8) added to the series
- 19th March, 2020: Article (7/8) added to the series
- 17th June, 2020 : Added final article of the series
- 1st March, 2023: Article update after framework refactory