X3DTK::X3D::Shape
node into X3DTK::X3D::InfoShape
. Moreover we want that X3DTK::X3D::Shape
belongs to a new component. If it has the type name "InfoShape", then a third party X3D application won't be able to load the new node because it doesn´t know it. Nevertheless X3DTK::X3D::InfoShape
can be seen like a X3DTK::X3D::Shape
in a classical X3D viewer. The only thing you have to do is to give the type name "Shape". More details about how to write a new node can be found here.Some important functions and classes:
X3DTK::X3D::InfoShape
has an X3DTK::X3D::Info
child which has a single attribute. The only thing to do is to give X3DTK::X3D::InfoShape
the type name "Shape". For more details about writing a parent node, see the infoReader example.defineComponentName
command.#ifndef INFOSHAPE_H #define INFOSHAPE_H #include <X3DTK/X3D/scenegraph.h> namespace X3DTK { namespace X3D { class Info; // InfoShape node. class InfoShape : public Shape { public: InfoShape(); virtual ~InfoShape(); inline Info *getInfo() const {return _info;}; private: Info *_info; }; } } #endif
#include "X3D_InfoShape.h" #include "X3D_Info.h" #include <iostream> using namespace std; namespace X3DTK { namespace X3D { InfoShape::InfoShape() : Shape() { // Defines the tag of the node. This string is the one read in the X3D file. // We give the name "Shape" to erase the older definition. define(Recorder<InfoShape>::getTypeName("Shape", "MyComponent")); // Defines a child node. define(Recorder<InfoShape, Info>::getSFNode("info", &InfoShape::_info)); } InfoShape::~InfoShape() { removeChildren(); } } }
#ifndef INFO_H #define INFO_H #include <X3DTK/X3D/scenegraph.h> namespace X3DTK { namespace X3D { // Info node. class Info : public X3DChildNode { public: Info(); virtual ~Info(); void setDescription(const SFString &description); inline const SFString &getDescription() const {return _description;}; private: SFString _description; }; } } #endif
#include "X3D_Info.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 the attributes. define(Recorder<Info, SFString>::getAttribute("description", &Info::_description, "no description")); } Info::~Info() { } void Info::setDescription(const SFString &description) { _description = description; } } }
#ifndef MYCOMPONENTCREATOR_H #define MYCOMPONENTCREATOR_H #include <X3DTK/X3D/scenegraph.h> namespace X3DTK { namespace X3D { // Component creator deriving the generic component creator and defining a new // component creator. class MyComponentCreator : public X3DComponentCreator { public: // Constructor. MyComponentCreator(); }; } } #endif
#include "X3D_MyComponentCreator.h" #include "X3D_InfoShape.h" namespace X3DTK { namespace X3D { MyComponentCreator::MyComponentCreator() : X3DComponentCreator() { defineComponentName("MyComponent", "X3D"); // Defines the new nodes. define(Recorder<InfoShape>::getCreationFunction()); } } }
#include <X3DTK/X3D/scenegraph.h> #include <X3DTK/graphtester.h> #include <X3DTK/memreleaser.h> #include "X3D_MyGroupingCreator.h" #include "X3D_MyComponentCreator.h" #include <iostream> using namespace X3DTK; using namespace std; int main(int argc, char *argv[]) { if (argc <= 1) { cerr << "usage: redefineNodeTester input" << endl; exit(0); } X3D::Loader *loader = Singleton<X3D::Loader>::getInstance(); loader->setComponentCreator(new X3D::MyGroupingCreator()); MemReleaser *releaser = Singleton<MemReleaser>::getInstance(); GraphTester *graphtester = Singleton<GraphTester>::getInstance(); // Loads the scene. X3D::Scene *s = loader->load(argv[1], false); graphtester->test(s); // Releases the scene. releaser->release(s); // adding new component creator. loader->setComponentCreator(new X3D::MyComponentCreator()); cout << "***Check x3dtk.log to see that Shape cannot have an Info child!***" << endl; // Loads the scene. s = loader->load(argv[1], false); graphtester->test(s); return 1; }