X3DTK::X3D::Info
node that can contain two nodes, X3DTK::X3D::Price
and X3DTK::X3D::Modeler
. We also define a new X3DTK::Date
type for the X3DTK::X3D::Info
node.Some important functions and classes:
X3DTK::SFString
and a toSFString
. These methods are used to load and write the type. We also overload the ostream operator to facilitate the use of the type.
Declaration of the XDTK::Date
type:
The constructor from anstruct Date { public: Date(); explicit Date(const SFString &date); SFString toSFString() const; int day; int month; int year; }; std::ostream& X3DTK::operator<<(std::ostream& o, const Date &date);
X3DTK::SFString
is made explicit to avoid implicit conversion. Notice that the assignement operator is implicitly defined, however you may define it, because it is used for the X3DTK::X3DAbstractNode::clone
method. The implementation of these methods are not X3DToolKit specific, nevertheless notice the difference between the ostream operator and the toSFString method. Unlike the ostream operator, the toSFString
method returns a string beginning and ending with the '"' character. This is the string written in the X3D file.X3DTK::X3D::Info
declaration: A node is defined by its attributes which can be atomic attributes or child nodes. An attribute ofclass Info : public X3DChildNode { public: Info(); virtual ~Info(); void setDate(const Date &date); inline const Date &getDate() const {return _date;}; inline Price *getPrice() const {return _price;}; inline Modeler *getModeler() const {return _modeler;}; private: Date _date; Price *_price; Modeler *_modeler; };
X3DTK::Date
type is defined for which a set
and get
method are defined. For the child nodes, only a get method is defined. Indeed a generic X3DTK::X3DAbstractNode::setChild
method is provided.Concerning the body definition of the constructor:
Type name, atomic attributes and child nodes are recorded thanks to the overloadedInfo::Info() : X3DChildNode() { define(Recorder<Info>::getTypeName("Info")); define(Recorder<Info, Date>::getAttribute("date", &Info::_date, Date())); define(Recorder<Info, Price>::getSFNode("price", &Info::_price)); define(Recorder<Info, Modeler>::getSFNode("modeler", &Info::_modeler)); }
X3DTK::X3DAbstractNode::define
function and the template Recorder class that collects necessary informations for the automated X3DTK::X3DAbstractNode::clone
, X3DTK::X3DAbstractNode::setChild
, X3DTK::X3DAbstractNode::getChildList
methods. Notice that the order of which child nodes are recorded appeared is important because, it defines the traversal order. It means that in a graph traversal the X3DTK::X3D::Price
node is traversed before the X3DTK::X3D::Modeler
node.The destructor is very simple:
A call toInfo::Info() { removeChildren(); }
X3DTK::X3DAbstractNode::removeChildren
is just needed. The links between the node and its children are broken.The body is also very simple:
The recording of the node is made thanks to the template recorder class. the syntax is very similar to the recording of the attributes and of the callback functions (see the simpleNodeCounter example).MyGroupingCreator::MyGroupingCreator() : GroupingCreator() { define(Recorder<Info>::getCreationFunction()); }
X3DTK::X3D::InfoReader
that extracts and displays the content of the nodes X3DTK::X3D::Info
, X3DTK::X3D::Price
and X3DTK::X3D::Modeler
. You can refer to glNormalViewer for an example page of processor creation.#ifndef DATE_H #define DATE_H #include <X3DTK/kernel.h> namespace X3DTK { struct Date { public: Date(); explicit Date(const SFString &date); SFString toSFString() const; int day; int month; int year; }; std::ostream& X3DTK::operator<<(std::ostream& o, const Date &date); } #endif
#include "Date.h" #include <iostream> using namespace std; namespace X3DTK { Date::Date() : day(0), month(0), year(0) { } Date::Date(const SFString &date) { SFString d, m, y; m = date.substr(0, 2); d = date.substr(3, 2); y = date.substr(6, 2); day = d.toInt(); month = m.toInt(); year = y.toInt(); } SFString Date::toSFString() const { SFString m = SFString::number(month); SFString d = SFString::number(day); SFString y = SFString::number(year); if (m.size() == 1) m = '0' + m; if (d.size() == 1) d = '0' + d; if (y.size() == 1) y = '0' + y; return "\"" + m + "/" + d + "/" + y + "\""; } std::ostream& X3DTK::operator<<(std::ostream& o, const Date &date) { return o << date.month << "/" << date.day << "/" << date.year; } }
#ifndef INFO_H #define INFO_H #include <X3DTK/X3D/scenegraph.h> #include "Date.h" namespace X3DTK { namespace X3D { class Price; class Modeler; // Info node. class Info : public X3DChildNode { public: Info(); virtual ~Info(); void setDate(const Date &date); inline const Date &getDate() const {return _date;}; inline Price *getPrice() const {return _price;}; inline Modeler *getModeler() const {return _modeler;}; private: Date _date; Price *_price; Modeler *_modeler; }; } } #endif
#include "X3D_Info.h" #include "X3D_Price.h" #include "X3D_Modeler.h" namespace X3DTK { namespace X3D { Info::Info() : X3DChildNode() { // Defines the tag of the node. This string is the one read in the X3D file. define(Recorder<Info>::getTypeName("Info")); // Defines an attribute. define(Recorder<Info, Date>::getAttribute("date", &Info::_date, Date())); // Defines a child node. define(Recorder<Info, Price>::getSFNode("price", &Info::_price)); define(Recorder<Info, Modeler>::getSFNode("modeler", &Info::_modeler)); } Info::~Info() { removeChidlren(); } void Info::setDate(const Date &date) { _date = date; } } }
#ifndef PRICE_H #define PRICE_H #include <X3DTK/X3D/scenegraph.h> namespace X3DTK { namespace X3D { // Price node. class Price : public X3DChildNode { public: Price(); virtual ~Price(); void setPrice(const SFFloat &price); void setMoney(const SFString &money); inline const SFFloat &getPrice() const {return _price;}; inline const SFString &getMoney() const {return _money;}; private: SFFloat _price; SFString _money; }; } } #endif
#include "X3D_Price.h" namespace X3DTK { namespace X3D { Price::Price() : X3DChildNode() { // Defines the tag of the node. This string is the one read in the X3D file. define(Recorder<Price>::getTypeName("Price")); // Defines the attributes. define(Recorder<Price, SFFloat>::getAttribute("price", &Price::_price, 0.0f)); define(Recorder<Price, SFString>::getAttribute("money", &Price::_money, "euro")); } Price::~Price() { } void Price::setPrice(const SFFloat &price) { _price = price; } void Price::setMoney(const SFString &money) { _money = money; } } }
#ifndef MODELER_H #define MODELER_H #include <X3DTK/X3D/scenegraph.h> namespace X3DTK { namespace X3D { // Modeler child node of Info. class Modeler : public X3DChildNode { public: Modeler(); virtual ~Modeler(); void setMName(const SFString &name); inline const SFString &getMName() const {return _mname;}; private: SFString _mname; }; } } #endif
#include "X3D_Modeler.h" namespace X3DTK { namespace X3D { Modeler::Modeler() : X3DChildNode() { // Defines the tag of the node. This string is the one read in the X3D file. define(Recorder<Modeler>::getTypeName("Modeler", "MyComponent")); // Defines an attribute. define(Recorder<Modeler, SFString>::getAttribute("mname", &Modeler::_mname, "")); } Modeler::~Modeler() { } void Modeler::setMName(const SFString &name) { _mname = name; } } }
#ifndef MYGROUPINGCREATOR_H #define MYGROUPINGCREATOR_H #include <X3DTK/X3D/scenegraph.h> namespace X3DTK { namespace X3D { // Component creator deriving the Grouping component creator defining the default // X3D nodes, plus the new ones. class MyGroupingCreator : public GroupingCreator { public: // Constructor. MyGroupingCreator(); }; } } #endif
#include "X3D_MyGroupingCreator.h" #include "X3D_Info.h" namespace X3DTK { namespace X3D { MyGroupingCreator::MyGroupingCreator() : GroupingCreator() { // Defines the new nodes. define(Recorder<Info>::getCreationFunction()); } } }
#ifndef INFOREADERGROUPINGVISITOR_H #define INFOREADERGROUPINGVISITOR_H #include <X3DTK/X3D/scenegraph.h> namespace X3DTK { namespace X3D { class Info; class Price; class Modeler; // Visitor for the Grouping component of the InfoReader processor. class InfoReaderGroupingVisitor : public GroupingVisitor { public: InfoReaderGroupingVisitor(); static void enterInfo(Info *I); static void enterPrice(Price *P); static void enterModeler(Modeler *M); }; } } #endif
#include "X3D_InfoReaderGroupingVisitor.h" #include "X3D_Info.h" #include "X3D_Price.h" #include "X3D_Modeler.h" #include <iostream> using namespace std; namespace X3DTK { namespace X3D { InfoReaderGroupingVisitor::InfoReaderGroupingVisitor() : GroupingVisitor() { // Enter functions. define(Recorder<Info>::getEnterFunction(&InfoReaderGroupingVisitor::enterInfo)); define(Recorder<Price>::getEnterFunction(&InfoReaderGroupingVisitor::enterPrice)); define(Recorder<Modeler>::getEnterFunction(&InfoReaderGroupingVisitor::enterModeler)); } void InfoReaderGroupingVisitor::enterInfo(Info *I) { cout << "Informations relative to the scene:"<< endl; cout << "Date = " << I->getDate() << endl; } void InfoReaderGroupingVisitor::enterPrice(Price *P) { cout << " price = " << P->getPrice() << " " << P->getMoney() << endl; } void InfoReaderGroupingVisitor::enterModeler(Modeler *M) { cout << " realized on the " << M->getMName() << " modeler" << endl; } } }
#ifndef INFOREADER_H #define INFOREADER_H #include <X3DTK/kernel.h> #include <X3DTK/X3D/scenegraph.h> namespace X3DTK { namespace X3D { // InfoReader processor. class InfoReader : public X3DOnePassProcessor { public: InfoReader(); virtual void read(SFNode N); }; } } #endif
#include "X3D_InfoReader.h" #include "X3D_InfoReaderGroupingVisitor.h" namespace X3DTK { namespace X3D { InfoReader::InfoReader() { // new GraphTraversal. setGraphTraversal(new DFSGraphTraversal()); // Setting the new component visitor. setComponentVisitor(new InfoReaderGroupingVisitor()); } void InfoReader::read(SFNode N) { traverse(N); } } }
#include "X3D_InfoReader.h" #include "X3D_MyGroupingCreator.h" #include <X3DTK/X3D/scenegraph.h> #include <X3DTK/X3D/scenesaver.h> #include <iostream> using namespace X3DTK; using namespace std; int main(int argc, char *argv[]) { if (argc <= 1) { cerr << "usage: infoReader input" << endl; exit(0); } // DefaultLoader to load the default X3D Nodes. X3D::Loader *loader = Singleton<X3D::Loader>::getInstance(); loader->setComponentCreator(new X3D::MyGroupingCreator()); // Instanciation of the new InfoReader. X3D::InfoReader *infoReader = Singleton<X3D::InfoReader>::getInstance(); X3D::SceneSaver *saver = Singleton<X3D::SceneSaver>::getInstance(); // Loads the scene. X3D::Scene *s = loader->load(argv[1], false); // reads the graph. infoReader->read(s); saver->saveAs(s, "myfile.x3d"); // Removes the instances. Singleton<X3D::InfoReader>::removeInstance(); Singleton<X3D::InfoReader>::removeInstance(); return 1; }