Creating a new Item3D widget for use in EMScene3D

To create a new Item3D widget use must inherit from EMItem3D (you will need to import this class from emitem3d). EMItem3D is a new style class so you don't need to multiply inherit from object. To make a valid object you must re-implement several method and redefine two attributes

  1. class(static) attribute: name, this gives a name for the new Item3D

  2. class(static) attribute: nodetype, this classifies to Item3D. This name can be the same as other Itme3Ds. For example if I were making a torus Item3D, I would name this as "Shapenode" because that is what Cubes, Spheres, etc are named.

  3. method: getEvalString(), this returns a string, which when evaled, creates an instance of this class. Generally you want this to create an instance of this class which is exactly the smae as the current instance because the purpose is for saving state.

  4. method: getItemInspector(), this needs to return an inspector for this widget.

  5. method: renderShape(), this implements the openGL code to actually render your object

For exmaple:

   1 class EMNewItem(EMItem3D):
   2     name = "myname"
   3     nodetype = "mynodetype"
   4     def __init__(self, parent=None, children=None, transform=None):
   5         if not Transform: transform=transform()
   6         EMItem3D.__init__(self,parent=parent,children=children,transform=transform)
   7         self.item_inspector = None
   8 
   9     def getEvalString(self):
  10         return EMNewItem()
  11 
  12     def getItemInspector(self):
  13         if not self.item_inspector: self.iteminspector = EMNewItemInspector("New", self)
  14         return self.item_inspector
  15 
  16     def renderShape(self):
  17         #Do open GL stuff

Enabling your new Item3D to be added to the 'add node' dialog

To allow your Item3D widget to be added to a scene graph using the 'add node' pushbutton(launches a dialog for adding nodes) in the SG inspector, you need to add two static functions to your Item3D class and add a few lines of code to the scene graph.

First add a static function to generate a dialog box to aid the user in adding an instance of this widget to the scene graph:

   1 class EMNewItem(EMItem3D):
   2     @staticmethod
   3     def getNodeDialogWidget(attribdict):
   4         mydialogwidget = QtGui.QWidget()
   5         grid = QtGui.QGridLayout()
   6         mylabel = QtGui.QLabel("My Label")
   7         attribdict["myparameter1"] = QtGui.QLineEdit("param1")
   8         grid.addWidget(mylabel,0 ,0)
   9         grid.addWidget(attribdict["myparameter1"])
  10         mydialogwidget.setLayout(grid)
  11         return mydialogwidget

Then you need to add another static function to actually generate an instance of this widget. In this example the fist argument to EMNewItem constructor is for this example, but the last argument is mandatory.

   1 class EMNewItem(EMItem3D):
   2     @staticmethod
   3     def getNodeForDialog(attribdict):
   4         return EMNewItem(attribdict["myparameter1"],transform=EMItem3D.getTransformFromDict(attribdict))

Next you need to add a few lines of code to the NodeDialog class in emscene3d.py, in two functions:

   1 class NodeDialog(QtGui.QDialog):
   2    def __init__(self, inspector, item):
   3         ...
   4         ...
   5         #populate node types
   6         self.node_type_combo.addItem(''"MyItem3D"'')
   7         self.myitem3d_dict = {}
   8         self.node_stacked_widget.addWidget(EMNewItem3D.getNodeDialogWidget(self.myitem3d_dict)
   9 
  10    def _on_add_node(self):
  11         ...
  12         ...
  13         #my item3d
  14         if self.node_type_combo.currentText() == "MyItem3D":
  15             insertionnode = EMNewItem3D.getNodeForDialog(self.myitem3d_dict)
  16             node_name = str(self.myitem3d_dict["node_name"].text())