Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

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".

Defining X3D::InfoShape, X3D::Price and X3D::Modeler

X3DTK::X3D::Price and X3DTK::X3D::Modeler are the same nodes that those defined in infoReader example. X3DTK::X3D::InfoShape is a mix between X3DTK::X3D::Shape and X3DTK::X3D::Info defined in infoReader. The only thing to do is to give X3DTK::X3D::InfoShape the type name "Shape".

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 INFO_H
#define INFO_H

#include <X3DTK/X3D/scenegraph.h>

namespace X3DTK {
namespace X3D {

class Price;
class Modeler;

// Info node.

class InfoShape : public Shape
{
public:
  InfoShape();
  virtual ~InfoShape();
  virtual SFAbstractNode clone() const;  

  void setDate(const SFString &date);
  void setPrice(Price *price);
  void setModeler(Modeler *modeler);  

  inline const SFString &getDate() const {return _date;};
  inline SFNode getPrice() const {return _price;};
  inline SFNode getModeler() const {return _modeler;};  
  
  virtual MFAbstractNode getChildList() const;
  
  virtual bool addChild(const SFAbstractNode &N);
  virtual bool setChild(const SFAbstractNode &N);
  virtual bool removeChild(const SFAbstractNode &N);
  
  virtual void load(const X3DFileElement *element);

protected:
  InfoShape(const InfoShape &I);

private:
  SFString _date;
  
  SFNode _price;
  SFNode _modeler;
};

}
}

#endif

X3D_InfoShape.cpp

#include "X3D_InfoShape.h"
#include "X3D_Price.h"
#include "X3D_Modeler.h"

#include <iostream>

using namespace std;

namespace X3DTK {
namespace X3D {

InfoShape::InfoShape()
: Shape(), _date("0/0/0"), _price(0), _modeler(0)
{
  // 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.
  defineTypeName("Shape", "MyComponent");
}

InfoShape::InfoShape(const InfoShape &I)
: Shape(I), _date(I._date), _price(I._price), _modeler(I._modeler)
{
}

InfoShape::~InfoShape()
{
  removeParentFromChild(this, _price);
  removeParentFromChild(this, _modeler);
}

SFAbstractNode InfoShape::clone() const
{
  return new InfoShape(*this);
}

void InfoShape::setDate(const SFString &date)
{
  _date = date;
}

void InfoShape::setPrice(Price *price)
{
  removeParentFromChild(this, _price);
  _price = price;
  addParentToChild(this, _price);
}

void InfoShape::setModeler(Modeler *modeler)
{
  removeParentFromChild(this, _modeler);
  _modeler = modeler;
  addParentToChild(this, _modeler);
}

MFAbstractNode InfoShape::getChildList() const
{
  MFAbstractNode childrenList = Shape::getChildList();
  if (_price != 0)
    childrenList.push_back(_price);
  if (_modeler != 0)
    childrenList.push_back(_modeler);  
    
  return childrenList; 
}

bool InfoShape::addChild(const SFAbstractNode &N)
{
  if (dynamic_cast<Price *>(N) != 0)
  {
    if (_price != 0)
      return false;
      
    setPrice(static_cast<Price *>(N));
    return true;
  }
  
  if (dynamic_cast<Modeler *>(N) != 0)
  {
    if (_modeler != 0)
      return false;
      
    setModeler(static_cast<Modeler *>(N));
    return true;    
  }
  
  Shape::addChild(N);
  
  return false;
}

bool InfoShape::setChild(const SFAbstractNode &N)
{
  if (dynamic_cast<Price *>(N) != 0)
  {
    setPrice(static_cast<Price *>(N));
    return true;
  }
  
  if (dynamic_cast<Modeler *>(N) != 0)
  {
    setModeler(static_cast<Modeler *>(N));
    return true;    
  }
  
  Shape::setChild(N);
  
  return false;
}

bool InfoShape::removeChild(const SFAbstractNode &N)
{
  if (_price == N)
  {
    setPrice(0);
    return true;
  }
  
  if (_modeler == N)
  {
    setModeler(0);
    return true;
  }
  
  Shape::removeChild(N);
  
  return false;
}

void InfoShape::load(const X3DFileElement *element)
{
  Shape::load(element);

  int index;
  index = element->getIndexAttribute("date");
  if (index != -1)
    _date = element->getAttribute(index);
}

}
}

X3D_Price.h

#ifndef PRICE_H
#define PRICE_H

#include <X3DTK/X3D/scenegraph.h>

namespace X3DTK {
namespace X3D {

// Price node.

class Price : public X3DChildNode
{
public:
  Price();
  Price(const SFFloat &price,
        const SFString &money);
            
  virtual SFAbstractNode clone() const;  
  void setPrice(const SFFloat &price);
  void setMoney(const SFString &money);

  inline const SFFloat &getPrice() const {return _price;};
  inline const SFString &getMoney() const {return _money;};
 
  virtual void load(const X3DFileElement *element);
  virtual SFString write() const;

protected:
  Price(const Price &I);

private:
  SFFloat _price;
  SFString _money;
};

}
}

#endif

X3D_Price.cpp

#include "X3D_Price.h"

namespace X3DTK {
namespace X3D {

Price::Price()
: X3DChildNode(), _price(0.0f), _money("euro")
{
  // Defines the tag of the node. This string is the one read in the X3D file.
  defineTypeName("Price");
}

Price::Price(const SFFloat &price, const SFString &money)
: X3DChildNode(), _price(price), _money(money)
{
  // Defines the tag of the node.
  defineTypeName("Price");
}

Price::Price(const Price &P)
: X3DChildNode(P), _price(P._price), _money(P._money)
{
}

SFAbstractNode Price::clone() const
{
  return new Price(*this);
}

void Price::setPrice(const SFFloat &price)
{
  _price = price;
}

void Price::setMoney(const SFString &money)
{
  _money = money;
}

void Price::load(const X3DFileElement *element)
{
  int index;
  index = element->getIndexAttribute("price");
  if (index != -1)
    _price = element->getAttribute(index).toFloat();
  
  index = element->getIndexAttribute("money");
  if (index != -1)
    _money = element->getAttribute(index);  
}

SFString Price::write() const
{
  SFString attr;
  if (_price != 0.0f)    
    attr += " price=\"" + toSFString(_price) + "\"";
  if (_money != "euro")
    attr += " money=\"" + _money + "\"";
      
  return attr;
}

}
}

X3D_Modeler.h

#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();
  Modeler(const SFString &name);
            
  virtual SFAbstractNode clone() const;  

  void setMName(const SFString &name);

  inline const SFString &getMName() const {return _name;};
 
  virtual void load(const X3DFileElement *element);
  virtual SFString write() const;

protected:
  Modeler(const Modeler &I);

private:
  SFString _name;
};

}
}

#endif

X3D_Modeler.cpp

#include "X3D_Modeler.h"

namespace X3DTK {
namespace X3D {

Modeler::Modeler()
: X3DChildNode(), _name("")
{
  // Defines the tag of the node. This string is the one read in the X3D file.
  defineTypeName("Modeler");
}

Modeler::Modeler(const SFString &name)
: X3DChildNode(), _name(name)
{
  // Defines the tag of the node.
  defineTypeName("Modeler");
}

Modeler::Modeler(const Modeler &P)
: X3DChildNode(P), _name(P._name)
{
}

SFAbstractNode Modeler::clone() const
{
  return new Modeler(*this);
}

void Modeler::setMName(const SFString &name)
{
  _name = name;
}

void Modeler::load(const X3DFileElement *element)
{
  int index;
  index = element->getIndexAttribute("name");
  if (index != -1)
    _name = element->getAttribute(index);  
}

SFString Modeler::write() const
{
  SFString attr;
  if (_name != "")    
    attr += " name=\"" + _name + "\"";
      
  return attr;
}

}
}

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();
  
  cout << "***Check x3dtk.log to see that Shape cannot have Price and Modeler children!***" << endl;
  
  // 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 can have Price and Modeler children!***" << endl;
  // Loads the scene.
  s = loader->load(argv[1], false);
  graphtester->test(s);
   
  return 1;
}

Generated on Thu Jun 3 10:12:14 2004 for X3DToolKit by doxygen 1.3.6