redefineNodeTester

Introduction

Sometimes, we want to redefine an existing node that has some interesting properties. Let's take the following example. We want to extend the 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:

Defining X3D::InfoShape, X3D::Info

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.

Defining X3D::MyComponentCreator

To load the new nodes, the creator for the new component is defined. It is necessary to give its name by the defineComponentName command.

Code

X3D_InfoShape.h

#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

X3D_InfoShape.cpp

#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();
}

}
}

X3D_Info.h

#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

X3D_Info.cpp

#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;
}

}
}

X3D_MyComponentCreator.h

#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

X3D_MyComponentCreator.cpp

#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());
}

}
}

main.cpp

#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;
}

Generated on Fri Aug 27 13:16:28 2004 for X3DToolKit by doxygen 1.3.6