Package DejaVu :: Package VisionInterface :: Module GeometryNodes
[hide private]
[frames] | no frames]

Source Code for Module DejaVu.VisionInterface.GeometryNodes

   1  ######################################################################## 
   2  # 
   3  # Date: Novembre 2005 Authors: Guillaume Vareille, Michel Sanner 
   4  # 
   5  #    vareille@scripps.edu 
   6  #    sanner@scripps.edu 
   7  # 
   8  #       The Scripps Research Institute (TSRI) 
   9  #       Molecular Graphics Lab 
  10  #       La Jolla, CA 92037, USA 
  11  # 
  12  # Copyright: Guillaume Vareille, Michel Sanner and TSRI 
  13  # 
  14  ######################################################################### 
  15  # 
  16  # $Header$ 
  17  # 
  18  # $Id$ 
  19  # 
  20   
  21  # third party packages  
  22  import os 
  23  from warnings import warn 
  24  from weakref import ref  
  25  from Numeric import array, identity 
  26  from Tkinter import Menu 
  27  from os.path import splitext 
  28   
  29  # TSRI packages 
  30  from mglutil.util.callback import CallBackFunction 
  31  from NetworkEditor.items import NetworkNode 
  32  from NetworkEditor.macros import MacroInputNode, MacroNetwork, \ 
  33                          MacroOutputNode, MacroOutputNode, MacroNode 
  34   
  35  from DejaVu.Common2d3dObject import Common2d3dObject 
  36  from DejaVu.Geom import Geom 
  37   
  38   
39 -class GeometryNode(NetworkNode):
40 """Base Class to hold a single geometry, should be only inherited, 41 never instanciated. it handles naming and parenting. 42 43 The geometry nodes handle a list of geometries. When the name changes, 44 a new geom is generated. If an empty name is provided, the current geometry 45 is deleted. 46 47 The parent and children connections reflect the state of the geometry selected 48 in the combo box. If the parent or children geoms are currently selected in 49 their own node: the connections are present. If the parent or a child is not 50 visible (for the selected geometry) the parent port or/and the output port 51 contour lines are white (instead of black). Before parenting you can set the 52 behaviour of the 'parent' inputport. Right clicking on the port allows you to 53 extend the parenting to the sibling geometries present in the node or to all 54 the geometries of the node. This behaviour set by right clicking will only 55 affect the next parenting. In the same way, deleting the parent connection, 56 reparent to 'root' the selected geometry or the sibling geometries or all the 57 geometries in the child node (depending on the right click menu choice). 58 59 THINGS TO DO TO INHERIT 60 (the best is to follow what is done in class IndexedPolygonsNE bellow) 61 1- inherit : 62 class IndexedPolygonsNE(GeometryNode): 63 2- at the beginning of init, call original init 64 (the 'indexedPolygons' in quotes will be the name of the output port): 65 kw['name'] = name 66 apply( GeometryNode.__init__, (self, 'indexedPolygons'), kw ) 67 3- rearrange ports order after appending additionnal input and output: 68 self.rearrangePorts() 69 4- at the beginning of doit, call original doit: 70 GeometryNode.doit(self, name, instanceMatrices, geomOptions, parent) 71 5- the doit function should really immitate the class IndexedPolygonsNE example 72 (parameters linked to input ports from the base class must be passed as last) 73 def doit(self, coords, indices, vnormals=None, colors=None, 74 name=None, instanceMatrices=None, geomOptions=None, parent=None): 75 6- override appendGeometry() 76 def appendGeometry(self, name): 77 from DejaVu.IndexedPolygons import IndexedPolygons 78 self.geoms.append(IndexedPolygons(name)) 79 return 1 # num of geoms appended 80 7- don't forget to use the new datatypes 81 ip.append(datatype='coord3(0,3)', name='coords') 82 83 GeomsFromFile bellow shows how the filename can be use as a director for 84 the name. It shows also how to append several geoms from one file. 85 86 If you want to read a new type of file the best is to add it inside 87 the appendGeometry of GeomsFromFile 88 """ 89
90 - def __init__(self, geomOutputPortName, **kw):
91 apply( NetworkNode.__init__, (self,), kw ) 92 93 self.geometriesOwner = True # tell if the node has created the geometries 94 # or is just displaying geometries 95 self.selectedGeomIndex = None 96 self.geoms = [] 97 98 # creat ports common to all geoemtry producing nodes 99 ip = self.inputPortsDescr 100 101 # for backward compatibility with old networks 102 # name and instanceMatrices must be the first ones in this Base class 103 ip.append(datatype='string', required=False, name='name') 104 ip.append(datatype='string', required=False, name='geoms') 105 ip.append(datatype='instancemat(0)', required=False, 106 name='instanceMatrices') 107 ip.append(datatype='dict', required=False, name='geomOptions') 108 # even if it is not compulsory, 109 # we try to keep the parent port in the last position 110 ip.append(datatype='geomOrInsert2d', required=False, name='parent', 111 singleConnection=True) 112 113 # used in rearrange Port and in afterConnect and afterDisconnect 114 self.numOfBaseClassInputPorts = len(ip) 115 116 op = self.outputPortsDescr 117 op.append(datatype='geomOrInsert2d', name=geomOutputPortName) 118 op.append(datatype='geomOrInsert2d', name='allGeometries') 119 120 self.widgetDescr['name'] = { 121 'class':'NEEntryNotScheduling', 122 'master':'node', 123 'width':12, 124 'labelCfg':{'text':'(next) name:'}, 125 'initialValue':geomOutputPortName, 126 } 127 128 self.widgetDescr['geoms'] = { 129 'class':'NEComboBox', 130 'master':'node', 131 'entryfield_entry_width':14, 132 'autoList':True, 133 'labelCfg':{'text':'geoms:'}, 134 } 135 136 codeAfterConnectParent = """def afterConnect(self, conn): 137 #print "codeAfterConnectParent", self.name 138 GeometryNode.afterConnectParent(self.node, self, conn) 139 """ 140 # this code runs when we connect something to the parent port 141 ip[self.numOfBaseClassInputPorts-1]['afterConnect'] = \ 142 codeAfterConnectParent 143 144 codeAfterDisconnectParent = """def afterDisconnect(self, p1, p2): 145 #print "codeAfterDisconnectParent", self.name 146 GeometryNode.afterDisconnectParent(self.node, p1) 147 """ 148 # this code runs when we disconnect something to the parent port 149 ip[self.numOfBaseClassInputPorts-1]['afterDisconnect'] = \ 150 codeAfterDisconnectParent 151 152 codeAfterDisconnectChildren = """def afterDisconnect(self, p1, p2): 153 #print "codeAfterDisconnectChildren", self.name 154 GeometryNode.afterDisconnectChildren(self.node, p1, p2) 155 """ 156 # this code runs when we disconnect something to the children port 157 op[0]['afterDisconnect'] = codeAfterDisconnectChildren
158 159
160 - def afterAddingToNetwork(self):
161 NetworkNode.afterAddingToNetwork(self) 162 if self.geometriesOwner is False: 163 self.inputPortByName['parent'].cascadeMenuVariable.set('none')
164 165
166 - def doit(self, name=None, geoms=None, instanceMatrices=None, 167 geomOptions=None, texture=None, parent=None):
168 #print "GeometryNode.doit", self.name 169 #print "geoms", geoms 170 if (self.inputPortByName['geoms'].hasNewData() is False) \ 171 or (self.selectedGeomIndex is None): 172 for g in self.geoms: 173 if name == g.name: 174 self.naming(name) 175 break 176 else: #we didn't break 177 if (self.selectedGeomIndex is not None) and (geoms == ''): 178 self.naming('') 179 elif name is not None \ 180 and ( self.inputPortByName['name'].hasNewData() \ 181 or self.selectedGeomIndex is None ) : 182 if name == '': 183 if self.name == 'the list is empty': 184 name = self.getOutputPortByType('geomOrInsert2d').name 185 else: 186 name = self.name 187 else: 188 wn = self.inputPortByName['name'].widget 189 if hasattr(wn,'widget'): 190 wn.set('', run=0) 191 self.addingEntries(name) 192 #self.parenting(parent) 193 self.reparentGeomType( 194 self.inputPortByName['parent'].cascadeMenuVariable.get(), 195 reparentCurrent=True) 196 elif (self.selectedGeomIndex is not None) \ 197 and (parent != self.geom().parent): 198 #self.parenting(parent) 199 self.reparentGeomType( 200 self.inputPortByName['parent'].cascadeMenuVariable.get(), 201 reparentCurrent=True) 202 else: 203 pass 204 else: 205 self.naming(geoms) 206 207 # we never want this to be set in the saved file, 208 # the network will do it through the saved name 209 self.inputPortByName['geoms'].widget._modified = False 210 211 self.drawParentAndChildrenConnections() 212 self.rebuildComboBoxList() 213 214 mat = None 215 if instanceMatrices: 216 mat = array(instanceMatrices) 217 else: 218 mat = [identity(4).astype('f')] 219 220 if mat is not None and self.selectedGeomIndex is not None: 221 #print self.geom(), mat 222 if geomOptions is not None: 223 opts = geomOptions.copy() 224 else: 225 opts = {} 226 227 if isinstance(self.geom(), Geom): 228 opts['instanceMatrices'] = mat 229 opts['redo'] = 0 230 opts['tagModified'] = False 231 apply( self.geom().Set, (), opts )
232 233
234 - def rearrangePorts(self):
235 """reoder port list for backwards compatibility. 236 (old network were saved with port indices instead of port names) 237 the parent and instance matrices ports are created by the base class 238 and therefore appear in position 1 and 2 but should move after the 239 ports created by the subclass. the port 'name' used to be index #4. 240 """ 241 #print "rearrangePorts" 242 ip = self.inputPortsDescr 243 if len(ip) > self.numOfBaseClassInputPorts: 244 self.inputPortsDescr = ip[self.numOfBaseClassInputPorts:] \ 245 + ip[:self.numOfBaseClassInputPorts]
246 247
248 - def geom(self):
249 #print "geom" 250 assert self.selectedGeomIndex is not None 251 #if len(self.geoms) == 0: 252 # self.selectedGeomIndex = None 253 assert len(self.geoms) > 0 254 assert self.selectedGeomIndex >= 0, self.selectedGeomIndex 255 assert self.selectedGeomIndex < len(self.geoms), self.selectedGeomIndex 256 return self.geoms[self.selectedGeomIndex]
257 258
259 - def removeAndCleanMultipleGeometryies(self, geometryies):
260 #print "removeAndCleanMultipleGeometryies", geometryies 261 if geometryies is None: 262 return 263 264 if isinstance(geometryies, Common2d3dObject): 265 if hasattr(geometryies, 'node'): 266 for g in geometryies.node().geoms: 267 self.removeAndCleanMultipleGeometryies(g.parent) 268 self.removeSingleGeom(g) 269 else: 270 for g in geometryies: 271 self.removeAndCleanMultipleGeometryies(g.parent) 272 self.removeSingleGeom(g)
273 274
275 - def removeSingleGeomAndReparentChildren(self, geom):
276 #print "removeSingleGeomAndReparentChildren", geom.name 277 if not isinstance(geom, Common2d3dObject): 278 return 279 280 if hasattr(geom, 'viewer'): 281 viewer = geom.viewer 282 else: 283 viewer = None 284 285 from copy import copy 286 lChildren = copy(geom.children) 287 for c in lChildren: 288 if hasattr(c, 'node'): 289 c.node().parenting(None,c) 290 elif viewer is not None: 291 viewer.ReparentObject(c, geom.parent) 292 293 if viewer is None: 294 return 295 296 if self.geometriesOwner is True: 297 geom.viewer.RemoveObject(geom) 298 geom.parent = None
299 300
301 - def removeSingleGeom(self, geom):
302 #print "removeSingleGeom", geom.name 303 if not isinstance(geom, Common2d3dObject): 304 return 305 306 if not hasattr(geom, 'viewer'): 307 return 308 309 if geom.viewer is None: 310 return 311 312 if self.geometriesOwner is True: 313 lViewer = geom.viewer 314 lViewer.RemoveObject(geom) 315 if geom.parent == lViewer.rootObject: 316 geom.parent = None
317 318
319 - def removeViewerConnection(self, doNotRemoveThisConnection = None):
320 #print "removeViewerConnection", doNotRemoveThisConnection.port1, doNotRemoveThisConnection.port2 321 lOutputPort = self.getOutputPortByType('geomOrInsert2d') 322 for c in lOutputPort.connections: 323 from DejaVu.VisionInterface.DejaVuNodes import Viewer 324 if c != doNotRemoveThisConnection: 325 if isinstance(c.port2.node, Viewer): 326 self.network.deleteConnectionsNoCB(c) 327 elif isinstance(c.port2.node, MacroOutputNode): 328 m = c.port2.node.macroNode 329 lOutputPortMacro = m.getOutputPortByName(c.port2.name) 330 for cm in lOutputPortMacro.connections: 331 if cm == doNotRemoveThisConnection: 332 break 333 elif isinstance(cm.port2.node, Viewer): 334 cm.network.deleteConnectionsNoCB(cm) 335 break
336 337
338 - def removeViewerConnections(self, doNotRemoveThisConnection = None):
339 #print "removeViewerConnections", doNotRemoveThisConnection 340 for g in self.geoms: 341 p = g.LastParentBeforeRoot() 342 for c in p.AllObjects(): 343 if hasattr(c,'node'): 344 c.node().removeViewerConnection(doNotRemoveThisConnection) 345 346
347 - def ensureNameOfNodeAndDescendants(self, obj):
348 #print "ensureNameOfNodeAndDescendants" 349 if len(self.geoms) > 0: 350 for geom in obj.AllObjects(): 351 if hasattr(geom,'node'): 352 geom.node().rebuildComboBoxList()
353 354
355 - def getIndexFromName(self, name):
356 """returns the index of the geom 357 returns -1 if entry is not in the list 358 """ 359 #print "getIndexFromName" 360 361 for i in range(len(self.geoms)): 362 if name == self.geoms[i].name: 363 return i 364 return -1
365 366
367 - def naming(self, name):
368 """ returns True if we need to perform Parenting 369 """ 370 #print "Naming old:" , self.name, "new:", name 371 372 if name is None: 373 return False 374 375 w0 = self.inputPortByName['geoms'].widget 376 if hasattr(w0,'widget'): 377 w = w0.widget 378 else: 379 w = None 380 self.inputPortByName['geoms']._previousWidgetDescr['choices'] = [] 381 382 if name == '': 383 #print "deleting entry", self.name 384 385 if w.size() == 0: 386 return False 387 388 if self.selectedGeomIndex is None: 389 #print "the list is empty 1" 390 w1 = self.inputPortByName['name'].widget 391 if hasattr(w1,'widget'): 392 w1.set(self.name, run=0) 393 self.rename("the list is empty") 394 if w is not None: 395 w.delete(0,'end') 396 return False 397 398 assert self.geom().name == self.name 399 400 #remove self.geom in the viewer 401 #and verify children renaming/reparenting 402 self.removeSingleGeomAndReparentChildren(self.geom()) 403 404 if w is not None: 405 if w.get(self.selectedGeomIndex) == self.name: 406 w.delete(self.selectedGeomIndex) 407 408 self.geoms.remove(self.geom()) 409 410 if len(self.geoms) > 0: 411 self.selectedGeomIndex = 0 412 self.rename(self.geom().name) 413 if w is not None: 414 w.selectitem(self.selectedGeomIndex,setentry=1) 415 else: 416 #print "the list is empty 2" 417 self.selectedGeomIndex = None 418 self.inputPortByName['name'].widget.set(self.name, run=0) 419 self.rename("the list is empty") 420 return False 421 422 index = self.getIndexFromName(name) 423 424 if index >= 0: 425 #print "selecting entry", name 426 self.selectedGeomIndex = index 427 assert self.selectedGeomIndex < len(self.geoms) , len(self.geoms) 428 self.rename(self.geom().name) 429 return False 430 else: 431 #print "renaming entries", name 432 self.geom().Set(name=name) 433 self.rename(self.geom().name) 434 return False 435 436
437 - def addingEntries(self, name):
438 #print "addingEntries", name 439 self.selectedGeomIndex = len(self.geoms) 440 lenMoreGeoms = self.appendGeometry(name) 441 if lenMoreGeoms > 0: 442 for i in range(lenMoreGeoms): 443 lIndex = self.selectedGeomIndex + i 444 self.geoms[lIndex].node = ref(self) 445 self.geoms[lIndex].replace = False 446 self.rename(self.geom().name) 447 elif len(self.geoms) > 0: 448 self.selectedGeomIndex = len(self.geoms) - 1 449 else: 450 self.selectedGeomIndex = None 451 452 assert self.selectedGeomIndex < len(self.geoms) , self.geoms 453 454 #to silent pychecker
455 - def appendGeometry(self, name):
456 assert False, name 457 pass
458 459
460 - def nodeOnlyGeomRemoval(self, geom):
461 #print "cleanNodeForGeomRemoval", geom.name 462 463 assert geom in self.geoms 464 465 if self.geom() == geom: 466 lThatIsTheSelectedOne = True 467 else: 468 lThatIsTheSelectedOne = False 469 470 self.geoms.remove(geom) 471 472 if lThatIsTheSelectedOne is True: 473 if len(self.geoms) > 0: 474 self.selectedGeomIndex = 0 475 self.rename(self.geom().name) 476 w0 = self.inputPortByName['geoms'].widget 477 if hasattr(w0,'widget'): 478 w0.widget.selectitem(self.selectedGeomIndex,setentry=1) 479 else: 480 #print "the list is empty 3" 481 self.selectedGeomIndex = None 482 self.inputPortByName['name'].widget.set(self.name, run=0) 483 self.rename("the list is empty")
484 485
486 - def parenting(self, parent, geom=None):
487 """ prepare the parenting and launch it if applicable 488 it will parent the selectedGeomIndex unless geom is provided 489 """ 490 #print "Parenting", parent , geom 491 #import traceback;traceback.print_stack() 492 #import pdb;pdb.set_trace() 493 494 if geom is None: 495 if self.selectedGeomIndex is None: 496 return 'Go' 497 geom = self.geom() 498 499 if geom.viewer is not None and parent is None: 500 parent = geom.viewer.rootObject 501 else: 502 if isinstance(parent, Common2d3dObject): 503 if hasattr(parent, 'node'): 504 if parent.node().selectedGeomIndex is not None: 505 parent = parent.node().geom() 506 else: 507 return 'Go' 508 #else: 509 # parent = parent 510 elif isinstance(parent, list): 511 if len(parent) > 0 and hasattr(parent[0], 'node'): 512 #Get the correct parent in the list 513 parent = parent[0].node().geom() 514 #parent = parent[parent[0].node().selectedGeomIndex] #same thing 515 else: 516 parent = None 517 else: 518 assert parent is None 519 geom.parent = None 520 521 if parent is not None and parent!=geom.parent: 522 #print "le parent" , parent 523 #print "le geom.parent" , geom.parent 524 if not self.effectiveParenting(parent, geom): 525 warn( \ 526 'the parent is either in another viewer or is a child of the geometry') 527 return 'Stop' # node fails to execute 528 529 return 'Go'
530 531
532 - def effectiveParenting(self, lParent, geom=None):
533 """try to reparent geometry, return True upon success 534 after this call the geometry has a valid name 535 it will parent the selectedGeomIndex unless geom is provided 536 """ 537 #print "EffectiveParenting" 538 539 if geom is None: 540 geom = self.geom() 541 542 if geom.viewer is None: # we cannot do anything yet because we do 543 geom.parent = lParent # not know the viewer yet 544 geom.fullName = geom.BuildFullName() 545 return True # lParent will be used when geom is added to Viewer 546 547 if lParent is None: 548 lParent = geom.viewer.rootObject 549 550 # try to reparent geometry 551 if lParent.viewer is None: 552 lHighestModifiedParent = \ 553 geom.viewer.AddObjectAndParents(lParent, parent=lParent.parent, 554 local=False) 555 else: 556 lHighestModifiedParent = geom 557 558 # get unique name among new parent's children 559 name = geom.viewer.ensureUniqueName(geom.name, lParent, local=False, exclude=geom) 560 #name = geom.viewer.ensureUniqueName(name, lParent, local=False, exclude=geom) 561 562 # set the geometry's name NOT using geom.Set() because parent is still 563 # the old one and geom.Set(name=..) checks name validity 564 geom.name = name 565 566 geom.viewer.ReparentObject(geom, lParent) 567 568 self.ensureNameOfNodeAndDescendants(lHighestModifiedParent) 569 570 #except AssertionError: # if parent is different viewer than geom 571 # # or ... 572 # return False 573 574 return True
575 576
577 - def drawParentAndChildrenConnections(self):
578 """ finds the selected children and parent 579 and draws the connections if they are selected in their own node 580 """ 581 #print "DrawParentAndChildrenConnections", self.name 582 583 if self.selectedGeomIndex is None: 584 return 585 586 # first we remove the existing parent connection 587 self.removeParentConnection() 588 589 # we remove the existing children connections 590 self.removeChildrenConnections() 591 592 # set the parent connection if parent is selected in his own node 593 self.setParentConnection() 594 595 # set the children connections when the children are selected 596 self.setChildrenConnections() 597 598
599 - def setParentConnection(self):
600 """ set the parent connection if parent is selected in his own node 601 """ 602 #print "setParentConnection", self 603 # first we set corectly the parent node children port 604 for g in self.geoms: 605 p = g.parent 606 v = g.viewer 607 if p is not None and v is not None and p != v.rootObject: 608 if hasattr(p,'node'): 609 p.node().setPortsOfTheChildrenConnections() 610 611 # then we set this node parent port 612 lParentPort = self.inputPortByName['parent'] 613 lParentPort.hasHiddenConnections = False 614 615 lParent = self.geom().parent 616 617 if lParent is None: 618 lParentPort.deleteIcon() 619 lParentPort.createIcon() 620 return 621 622 viewer = self.geom().viewer 623 if viewer is not None and lParent == viewer.rootObject: 624 lParentPort.deleteIcon() 625 lParentPort.createIcon() 626 return 627 628 if hasattr(lParent,'node'): 629 lParentNode = lParent.node() 630 if (lParentNode.selectedGeomIndex is not None) \ 631 and (self.geom().parent == lParentNode.geom() ): 632 633 lParentNodeOutputPort = lParentNode.getOutputPortByType('geomOrInsert2d') 634 635 if lParentNode.network == self.network: 636 self.network.connectNodes(lParentNode, self, 637 lParentNodeOutputPort.name, 638 'parent', 639 doNotScheduleOrCb=True) 640 elif isinstance(self.network, MacroNetwork): 641 #import pdb;pdb.set_trace() 642 lMacroNode = self.network.macroNode 643 while lParentNode.network != lMacroNode.network: 644 lMacroNode = lMacroNode.network.macroNode 645 lPortNameInMacro = self.name + '_parent' 646 if lMacroNode.inputPortByName.has_key(lPortNameInMacro) is False: 647 for p in lMacroNode.inputPorts: 648 if p.name.endswith('_parent'): 649 lPortNameInMacro = p.name 650 break 651 else: #we didn't break 652 assert "weird! we should have found the port _parent" 653 lParentNode.network.connectNodes( 654 lParentNode, 655 lMacroNode, 656 lParentNodeOutputPort.name, 657 lPortNameInMacro, 658 doNotScheduleOrCb=True) 659 elif isinstance(lParentNode.network, MacroNetwork): 660 #import pdb;pdb.set_trace() 661 lMacroNode = lParentNode.network.macroNode 662 while self.network != lMacroNode.network: 663 lMacroNode = lMacroNode.network.macroNode 664 lPortNameInMacro = lParentNode.name + '_' + lParentNodeOutputPort.name 665 if lMacroNode.outputPortByName.has_key(lPortNameInMacro) is False: 666 for p in lMacroNode.outputPorts: 667 if p.name.endswith('_' + lParentNodeOutputPort.name): 668 lPortNameInMacro = p.name 669 break 670 else: #we didn't break 671 assert "weird! we should have found the port _%s"%lParentNodeOutputPort.name 672 lMacroNode.network.connectNodes( 673 lMacroNode, 674 self, 675 lPortNameInMacro, 676 'parent', 677 doNotScheduleOrCb=True) 678 # TODO: make sure the white/black outline is set on the ports 679 #lMacroNode.inputPortByName[lPortNameInMacro].deleteIcon() 680 #lMacroNode.inputPortByName[lPortNameInMacro].createIcon() 681 else: 682 lParentPort.hasHiddenConnections = True 683 else: 684 # if len(lParentPort.connections) == 1: 685 # #if lParent != lParentPort.connections[0].port1.data: 686 # if lParent != lParentPort.getData(): 687 # lParentPort.hasHiddenConnections = True 688 # if len(lParentPort.connections) == 0: 689 # if not ( (lParent is None) \ 690 # or ( (self.geom().viewer is not None) \ 691 # and (lParent == self.geom().viewer.rootObject) ) ): 692 # lParentPort.hasHiddenConnections = True 693 694 if lParent != lParentPort.getData(): 695 if not ( (lParent is None) \ 696 or ( (self.geom().viewer is not None) \ 697 and (lParent == self.geom().viewer.rootObject) ) ): 698 lParentPort.hasHiddenConnections = True 699 700 lParentPort.deleteIcon() 701 lParentPort.createIcon()
702 703
704 - def removeParentConnection(self):
705 #print "removeParentConnection", self 706 707 lParentPort = self.inputPortByName['parent'] 708 for c in lParentPort.connections[::-1]: # going backwards 709 if isinstance(c.port1.node, GeometryNode) is True: 710 self.network.deleteConnectionsNoCB(c) 711 elif isinstance(c.port1.node, MacroInputNode) is True: 712 if self.geom().parent is None: 713 continue 714 if self.geom().viewer is not None \ 715 and self.geom().parent == self.geom().viewer.rootObject: 716 continue 717 lParentNode = self.geom().parent.node() 718 lParentNetwork = lParentNode.network 719 lMacroNode = c.port1.node 720 lMacroNetwork = lMacroNode.network 721 while lParentNetwork != lMacroNetwork: 722 lMacroNode = lMacroNetwork.macroNode 723 lMacroNetwork = lMacroNode.network 724 lPortNameInMacro = self.name + '_parent' 725 if lMacroNode.inputPortByName.has_key(lPortNameInMacro) is False: 726 for p in lMacroNode.inputPorts: 727 if p.name.endswith('_parent'): 728 lPortNameInMacro = p.name 729 break; 730 else: #we didn't break 731 assert "weird! we should have found the port _parent" 732 lConnections = lMacroNode.inputPortByName[lPortNameInMacro].connections 733 if len(lConnections) > 0: 734 # there is a unique connection 735 lMacroNetwork.deleteConnectionsNoCB(lConnections[0]) 736 else: 737 #needed for macro node 738 self.effectiveParenting(None) 739 elif self.selectedGeomIndex is not None: 740 if self.geom().parent is None: 741 self.network.deleteConnectionsNoCB(c) 742 elif self.geom().viewer is not None \ 743 and self.geom().parent == self.geom().viewer.rootObject: 744 self.network.deleteConnectionsNoCB(c) 745 elif self.geom().parent != lParentPort.getData(): 746 self.network.deleteConnectionsNoCB(c) 747 748
749 - def setChildrenConnections(self):
750 #print "setChildrenConnections" 751 for lChild in self.geom().children: 752 if hasattr(lChild, 'node'): 753 if lChild == lChild.node().geom(): # the child is selected in its node 754 lChild.node().setParentConnection() 755 756 self.setPortsOfTheChildrenConnections() 757 758
759 - def setPortsOfTheChildrenConnections(self):
760 #print "setPortsOfTheChildrenConnections" 761 lChildPort = self.getOutputPortByType('geomOrInsert2d') 762 lChildPort.hasHiddenConnections = False 763 764 for lChild in self.geom().children: 765 if hasattr(lChild, 'node'): 766 lOtherPort = lChild.node().inputPortByName['parent'] 767 if lChild == lChild.node().geom(): 768 # the child is selected in its node 769 lOtherPort.hasHiddenConnections = False 770 lOtherPort.deleteIcon() 771 lOtherPort.createIcon() 772 else: 773 lChildPort.hasHiddenConnections = True 774 775 lChildPort.deleteIcon() 776 lChildPort.createIcon() 777 778
779 - def removeChildrenConnections(self):
780 #print "removeChildrenConnections" 781 for lChild in self.geom().children: 782 if hasattr(lChild, 'node'): 783 if lChild == lChild.node().geom(): # the child is selected in its node 784 lChild.node().removeParentConnection() 785 786
787 - def rebuildComboBoxList(self):
788 """ """ 789 #print "RebuildComboBoxList" 790 w0 = self.inputPortByName['geoms'].widget 791 if not hasattr(w0,'widget'): 792 return 793 w = w0.widget 794 w.delete(0,'end') 795 if self.selectedGeomIndex is None: 796 w.setentry('') 797 return 798 for g in self.geoms: 799 w.insert('end',g.name) 800 w.selectitem(self.selectedGeomIndex,setentry=1) 801 lName = self.geom().name 802 if self.name != lName: 803 self.rename(lName)
804 805
806 - def reparentGeoms(self, list):
807 #print "reparentGeoms", list 808 809 parent = self.inputPortByName['parent'].getData() 810 #print "parent", parent 811 for g in list: 812 self.parenting(parent,g)
813 814
815 - def reparentGeomType(self, type, reparentCurrent = True):
816 #print "reparentGeomType", type 817 818 if self.selectedGeomIndex is None: 819 return 820 821 lGeomsToReparent = [] 822 geom = self.geom() 823 if type == 'current': 824 lGeomsToReparent.append(geom) 825 elif type == 'siblings': 826 # build list of siblings 827 for g in self.geoms: 828 if g is not geom or reparentCurrent is True: 829 #print g.parent 830 #print geom.parent 831 if g.parent is geom.parent: 832 lGeomsToReparent.append(g) 833 elif type == 'all': 834 # build list 835 assert type == 'all' , type 836 for g in self.geoms: 837 if g is not geom or reparentCurrent is True: 838 lGeomsToReparent.append(g) 839 else: 840 assert type == 'none' , type 841 self.reparentGeoms(lGeomsToReparent)
842 843
844 - def getViewerConnection(self, node):
845 #print "getViewerConnection", self.name 846 lOutputPort = node.getOutputPortByType('geomOrInsert2d') 847 for c in lOutputPort.connections: 848 from DejaVu.VisionInterface.DejaVuNodes import Viewer 849 if isinstance(c.port2.node, Viewer): 850 return c 851 elif isinstance(c.port2.node, MacroOutputNode): 852 m = c.port2.node.macroNode 853 lOutputPortMacro = m.getOutputPortByName(c.port2.name) 854 for cm in lOutputPortMacro.connections: 855 if isinstance(cm.port2.node, Viewer): 856 return cm 857 # elif isinstance(c.port2.node, MacroNode): 858 # lViewerNode = self.getViewerConnection(c.port2.node) 859 # if lViewerNode is not None: 860 # return lViewerNode 861 # elif hasattr(c.port2.node, 'getViewerConnection'): 862 # lViewerNode = c.port2.node.getViewerConnection(c.port2.node) 863 # if lViewerNode is not None: 864 # return lViewerNode 865 else: 866 lViewerNode = self.getViewerConnection(c.port2.node) 867 if lViewerNode is not None: 868 return lViewerNode 869 else: 870 return None 871 872
873 - def afterDisconnectParent(self, p1):
874 #print "GeometryNode afterDisconnectParent" 875 #import pdb;pdb.set_trace() 876 877 lViewerConnection = self.getViewerConnection(self) 878 if lViewerConnection is not None: 879 lParentNode = p1.node 880 if isinstance(lParentNode, GeometryNode): 881 lParentOutputPort = lParentNode.getOutputPortByType('geomOrInsert2d') 882 lViewerGeomPort = lViewerConnection.port2 883 if lParentNode.network == lViewerGeomPort.node.network: 884 self.network.connectNodes( 885 lParentNode, 886 lViewerGeomPort.node, 887 lParentOutputPort.name, 888 lViewerGeomPort.name, 889 doNotScheduleOrCb=True) 890 891 self.parenting(None) 892 self.rebuildComboBoxList()
893 894
895 - def afterConnectParent(self, port, conn):
896 #print "GeometryNode afterConnectParent" 897 if port.getData() == 'Stop': 898 port.data = None 899 else: 900 if self.selectedGeomIndex is not None: 901 self.reparentGeomType(conn.port2.cascadeMenuVariable.get(), 902 reparentCurrent=True) 903 self.rebuildComboBoxList()
904 905
906 - def afterDisconnectChildren(self, p1, p2):
907 #print "GeometryNode afterDisconnectChildren", self.name 908 #import pdb;pdb.set_trace() 909 910 if hasattr(p2, 'node'): 911 lChidrenNode = p2.node 912 if isinstance(lChidrenNode, MacroNode): 913 lViewerConnection = self.getViewerConnection(lChidrenNode) 914 if lViewerConnection is not None: 915 lParentNode = p1.node 916 lParentOutputPort = lParentNode.getOutputPortByType('geomOrInsert2d') 917 lViewerGeomPort = lViewerConnection.port2 918 if lParentNode.network == lViewerGeomPort.node.network: 919 self.network.connectNodes( 920 lParentNode, 921 lViewerGeomPort.node, 922 lParentOutputPort.name, 923 lViewerGeomPort.name, 924 doNotScheduleOrCb=True)
925 926
927 - def beforeRemovingFromNetwork(self):
928 #print "beforeRemovingFromNetwork" 929 #self.removeParentConnection() 930 if len(self.geoms) > 0: 931 #self.removeChildrenConnections() 932 for g in self.geoms: 933 self.removeSingleGeomAndReparentChildren(g)
934 935
936 - def textureManagement(self, image, textureCoordinates=None):
937 if image is not None and self.selectedGeomIndex is not None: 938 g = self.geom() 939 from DejaVu.Texture import Texture 940 lTexture = Texture(enable=1, image=image) 941 if textureCoordinates is not None: 942 g.Set(texture=lTexture, textureCoords=textureCoordinates) 943 else: 944 g.Set(texture=lTexture) 945 if hasattr(g.vertexSet, 'texCoords'): 946 g.vertexSet.texCoords.array = \ 947 lTexture.getTextureCoordinatesAfterResizeRatio( 948 g.vertexSet.texCoords.array)
949 950
951 -class IndexedPolygonsNE(GeometryNode):
952 """Build a geometry for drawing a set of polygons sharing vertices. 953 954 The geometry nodes handle a list of geometries. When the name changes, 955 a new geom is generated. If an empty name is provided, the current geometry 956 is deleted. 957 958 The parent and children connections reflect the state of the geometry selected 959 in the combo box. If the parent or children geoms are currently selected in 960 their own node: the connections are present. If the parent or a child is not 961 visible (for the selected geometry) the parent port or/and the output port 962 contour lines are white (instead of black). Before parenting you can set the 963 behaviour of the 'parent' inputport. Right clicking on the port allows you to 964 extend the parenting to the sibling geometries present in the node or to all 965 the geometries of the node. This behaviour set by right clicking will only 966 affect the next parenting. In the same way, deleting the parent connection, 967 reparent to 'root' the selected geometry or the sibling geometries or all the 968 geometries in the child node (depending on the right click menu choice). 969 970 Input Ports: 971 coords: Nx3 floating points values (type coordinates3D) 972 indices: nested lists of indices (1 tuple per polygon) 973 vnormals:normal vectors at each vertex 974 colors: list of RGB tuples (optional) 975 name: name of the geometry 976 instanceMatrices: stream of 4x4 transformation matrices (default identity) 977 parent: a geometry to parent the selected geometry (default root) 978 979 Output Ports: 980 indexedPolygons: IndexedPolygons geometry 981 allGeometries: list of all the geometries in the node 982 """ 983
984 - def __init__(self, name='indexedPolygons', **kw):
985 986 kw['name'] = name 987 apply( GeometryNode.__init__, (self, 'indexedPolygons'), kw ) 988 989 ip = self.inputPortsDescr 990 ip.append(datatype='coord3(0)', name='coords') 991 ip.append(datatype='indice3or4(0)', name='indices') 992 ip.append(datatype='normal3(0)', required=False, name='vnormals') 993 ip.append(datatype='colorfloat3or4(0)', required=False, name='colors') 994 ip.append(datatype='image', required=False, name='image') 995 ip.append(datatype='coord2(0)', required=False, name='textureCoordinates') 996 997 # for backward compatibility 998 # this make sure that the first ports in the node are the ones 999 # that use to be there before we introduced the GeometryNode class 1000 # (old network were saved with port indices instead of port names) 1001 self.rearrangePorts() 1002 1003 code = """def doit(self, coords, indices, vnormals=None, colors=None, 1004 image=None, textureCoordinates=None, 1005 name=None, geoms=None, instanceMatrices=None, geomOptions=None, parent=None): 1006 #print "doit", self.name 1007 #apply( GeometryNode.doit, (self,)+args ) 1008 1009 GeometryNode.doit(self, name=name, geoms=geoms, 1010 instanceMatrices=instanceMatrices, 1011 geomOptions=geomOptions, parent=parent) 1012 1013 if self.selectedGeomIndex is not None: 1014 g = self.geom() 1015 if colors is not None: 1016 inheritMaterial = False 1017 else: 1018 inheritMaterial = None 1019 g.Set(vertices=coords, faces=indices, materials=colors, 1020 tagModified=False, 1021 vnormals=vnormals, inheritMaterial=inheritMaterial ) 1022 1023 GeometryNode.textureManagement(self, 1024 image=image, 1025 textureCoordinates=textureCoordinates) 1026 1027 self.outputData(indexedPolygons=self.geom(), allGeometries=self.geoms) 1028 else: 1029 self.outputData(indexedPolygons=None, allGeometries=self.geoms) 1030 """ 1031 if code: self.setFunction(code)
1032 1033
1034 - def appendGeometry(self, name):
1035 from DejaVu.IndexedPolygons import IndexedPolygons 1036 self.geoms.append(IndexedPolygons(name=name)) 1037 return 1 # num of geoms appended
1038 1039 1040
1041 -class IndexedPolylinesNE(GeometryNode):
1042 """Build a geometry for drawing a set of lines sharing vertices. 1043 1044 The geometry nodes handle a list of geometries. When the name changes, 1045 a new geom is generated. If an empty name is provided, the current geometry 1046 is deleted. 1047 1048 The parent and children connections reflect the state of the geometry selected 1049 in the combo box. If the parent or children geoms are currently selected in 1050 their own node: the connections are present. If the parent or a child is not 1051 visible (for the selected geometry) the parent port or/and the output port 1052 contour lines are white (instead of black). Before parenting you can set the 1053 behaviour of the 'parent' inputport. Right clicking on the port allows you to 1054 extend the parenting to the sibling geometries present in the node or to all 1055 the geometries of the node. This behaviour set by right clicking will only 1056 affect the next parenting. In the same way, deleting the parent connection, 1057 reparent to 'root' the selected geometry or the sibling geometries or all the 1058 geometries in the child node (depending on the right click menu choice). 1059 1060 Input Ports: 1061 coords: Nx3 floating points values (type coordinates3D) 1062 indices: nested lists of indices (1 tuple per line) 1063 colors: list of RGB tuples (optional) 1064 name: name of the geometry 1065 instanceMatrices: stream of 4x4 transformation matrices (default identity) 1066 parent: a geometry to parent the selected geometry (default root) 1067 1068 Output Ports: 1069 indexedPolylines: IndexedPolylines geometry 1070 allGeometries: list of all the geometries in the node 1071 """ 1072
1073 - def __init__(self, name='indexedPolylines', **kw):
1074 1075 kw['name'] = name 1076 apply( GeometryNode.__init__, (self,'indexedPolylines'), kw ) 1077 1078 ip = self.inputPortsDescr 1079 ip.append(datatype='coord3(0)', name='coords') 1080 ip.append(datatype='indice2+(0)', name='indices') 1081 ip.append(datatype='normal3(0)', required=False, name='vnormals') 1082 ip.append(datatype='colorfloat3or4(0)', required=False, name='colors') 1083 ip.append(datatype='image', required=False, name='image') 1084 ip.append(datatype='coord2(0)', required=False, name='textureCoordinates') 1085 1086 # for backward compatibility 1087 # this make sure that the first ports in the node are the ones 1088 # that use to be there before we introduced the GeometryNode class 1089 # (old network were saved with port indices instead of port names) 1090 self.rearrangePorts() 1091 1092 code = """def doit(self, coords, indices, vnormals=None, colors=None, 1093 image=None, textureCoordinates=None, 1094 name=None, geoms=None, instanceMatrices=None, geomOptions=None, parent=None): 1095 #print "doit", self.name 1096 GeometryNode.doit(self, name=name, geoms=geoms, 1097 instanceMatrices=instanceMatrices, 1098 geomOptions=geomOptions, parent=parent) 1099 1100 if self.selectedGeomIndex is not None: 1101 g = self.geom() 1102 if colors is not None: 1103 inheritMaterial = False 1104 else: 1105 inheritMaterial = None 1106 g.Set(vertices=coords, faces=indices, materials=colors, tagModified=False, 1107 vnormals=vnormals, inheritMaterial=inheritMaterial) 1108 1109 GeometryNode.textureManagement(self, 1110 image=image, 1111 textureCoordinates=textureCoordinates) 1112 1113 self.outputData(indexedPolylines=g, allGeometries=self.geoms) 1114 else: 1115 self.outputData(indexedPolylines=None, allGeometries=self.geoms) 1116 """ 1117 if code: self.setFunction(code)
1118 1119
1120 - def appendGeometry(self, name):
1121 from DejaVu.IndexedPolylines import IndexedPolylines 1122 self.geoms.append(IndexedPolylines(name)) 1123 return 1 # num of geoms appended
1124 1125 1126
1127 -class Cylinders(GeometryNode):
1128 """Build a geometry for drawing a set of cylinders. 1129 1130 The geometry nodes handle a list of geometries. When the name changes, 1131 a new geom is generated. If an empty name is provided, the current geometry 1132 is deleted. 1133 1134 The parent and children connections reflect the state of the geometry selected 1135 in the combo box. If the parent or children geoms are currently selected in 1136 their own node: the connections are present. If the parent or a child is not 1137 visible (for the selected geometry) the parent port or/and the output port 1138 contour lines are white (instead of black). Before parenting you can set the 1139 behaviour of the 'parent' inputport. Right clicking on the port allows you to 1140 extend the parenting to the sibling geometries present in the node or to all 1141 the geometries of the node. This behaviour set by right clicking will only 1142 affect the next parenting. In the same way, deleting the parent connection, 1143 reparent to 'root' the selected geometry or the sibling geometries or all the 1144 geometries in the child node (depending on the right click menu choice). 1145 1146 Input Ports: 1147 coords: Nx3 floating points values (type coordinates3D) 1148 indices: nested lists of indices (1 tuple per line) 1149 colors: list of RGB tuples (optional) 1150 radius: float or list of floats of same length as coords (default is 1.0) 1151 quality: cylinder quality, the hight, the more polygons are drawn (default 5) 1152 (bound to a Thumbwheel in node) 1153 name: name of the geometry 1154 instanceMatrices: stream of 4x4 transformation matrices (default identity) 1155 parent: a geometry to parent the selected geometry (default root) 1156 1157 Output Ports: 1158 Cylinders: Cylinders geometry 1159 allGeometries: list of all the geometries in the node 1160 """ 1161
1162 - def __init__(self, name='cylinders', **kw):
1163 1164 kw['name'] = name 1165 apply( GeometryNode.__init__, (self,'cylinders'), kw ) 1166 1167 ip = self.inputPortsDescr 1168 ip.append(datatype='coord3(0)', name='coords') 1169 ip.append(datatype='indice2+(0)', name='indices') 1170 ip.append(datatype='colorfloat3or4(0)', required=False, name='colors') 1171 ip.append(datatype='float(0)', required=False, name='radius') 1172 ip.append(datatype='int', required=False, name='quality') 1173 ip.append(datatype='image', required=False, name='image') 1174 1175 # for backward compatibility 1176 # this make sure that the first ports in the node are the ones 1177 # that use to be there before we introduced the GeometryNode class 1178 # (old network were saved with port indices instead of port names) 1179 self.rearrangePorts() 1180 1181 self.widgetDescr['quality'] = { 1182 'class':'NEThumbWheel', 'master':'node', 'initialValue':5, 1183 'labelCfg':{'text':'quality:'}, 'width':80, 'height':20, 1184 'type':'int', 'oneTurn':10, 'lockBMin':1, 'min':0, 'wheelPad':2 } 1185 1186 self.widgetDescr['radius'] = { 1187 'class':'NEThumbWheel', 'master':'node', 'initialValue':1.0, 1188 'labelCfg':{'text':'radius:'}, 'width':80, 'height':20, 1189 'type':'float', 'oneTurn':10., 'lockBMin':1, 'min':0.1, 1190 'wheelPad':2 } 1191 1192 code = """def doit(self, coords, indices, colors=None, 1193 radius=1.0, quality=5, 1194 image=None, 1195 name=None, geoms=None, instanceMatrices=None, geomOptions=None, parent=None): 1196 #print "doit", self.name 1197 GeometryNode.doit(self, name=name, geoms=geoms, 1198 instanceMatrices=instanceMatrices, 1199 geomOptions=geomOptions, parent=parent) 1200 1201 if self.selectedGeomIndex is not None: 1202 g = self.geom() 1203 if colors is not None: 1204 inheritMaterial = False 1205 else: 1206 inheritMaterial = None 1207 g.Set(vertices=coords, faces=indices, materials=colors, tagModified=False, 1208 radii=radius, quality=quality, inheritMaterial=inheritMaterial) 1209 1210 GeometryNode.textureManagement(self, image=image) 1211 1212 self.outputData(cylinders=g, allGeometries=self.geoms) 1213 else: 1214 self.outputData(cylinders=None, allGeometries=self.geoms) 1215 """ 1216 if code: self.setFunction(code)
1217 1218
1219 - def appendGeometry(self, name):
1220 from DejaVu.Cylinders import Cylinders 1221 self.geoms.append(Cylinders(name)) 1222 return 1 # num of geoms appended
1223 1224 1225
1226 -class AxisNE(GeometryNode):
1227 """Build a CylinderArrow geometry for drawing an AXIS. 1228 1229 The geometry nodes handle a list of geometries. When the name changes, 1230 a new geom is generated. If an empty name is provided, the current geometry 1231 is deleted. 1232 1233 The parent and children connections reflect the state of the geometry selected 1234 in the combo box. If the parent or children geoms are currently selected in 1235 their own node: the connections are present. If the parent or a child is not 1236 visible (for the selected geometry) the parent port or/and the output port 1237 contour lines are white (instead of black). Before parenting you can set the 1238 behaviour of the 'parent' inputport. Right clicking on the port allows you to 1239 extend the parenting to the sibling geometries present in the node or to all 1240 the geometries of the node. This behaviour set by right clicking will only 1241 affect the next parenting. In the same way, deleting the parent connection, 1242 reparent to 'root' the selected geometry or the sibling geometries or all the 1243 geometries in the child node (depending on the right click menu choice). 1244 1245 Input Ports: 1246 coords: list of pairs of 3D points [((x1,y1,z1),(x2,y2,z2)) ...] (optional) 1247 indices: nested lists of indices (1 tuple per line) 1248 colors: list of RGB tuples (optional) 1249 radius: float or list of floats of same length as coords (default is 1.0) 1250 quality: cylinder quality, the hight, the more polygons are drawn (default 5) 1251 (bound to a Thumbwheel in node) 1252 headLength: 1253 headRadius: 1254 name: name of the geometry 1255 instanceMatrices: stream of 4x4 transformation matrices (default identity) 1256 parent: a geometry to parent the selected geometry (default root) 1257 1258 Output Ports: 1259 Axis: CylinderArrows geometry 1260 allGeometries: list of all the geometries in the node 1261 """ 1262
1263 - def __init__(self, name='axis', **kw):
1264 1265 kw['name'] = name 1266 apply( GeometryNode.__init__, (self,'axis'), kw ) 1267 1268 ip = self.inputPortsDescr 1269 ip.append(datatype='coord3(0)', required=False, name='coords') 1270 ip.append(datatype='indice2+(0)', required=False, name='indices') 1271 ip.append(datatype='colorfloat3or4(0)', required=False, name='colors') 1272 ip.append(datatype='float(0)', required=False, name='radius') 1273 ip.append(datatype='int', required=False, name='quality') 1274 ip.append(datatype='float', required=False, name='headLength') 1275 ip.append(datatype='float', required=False, name='headRadius') 1276 ip.append(datatype='image', required=False, name='image') 1277 1278 # for backward compatibility 1279 # this make sure that the first ports in the node are the ones 1280 # that use to be there before we introduced the GeometryNode class 1281 # (old network were saved with port indices instead of port names) 1282 self.rearrangePorts() 1283 1284 self.widgetDescr['quality'] = { 1285 'class':'NEThumbWheel', 'master':'node', 'initialValue':5, 1286 'labelCfg':{'text':'quality:'}, 'width':80, 'height':20, 1287 'type':'int', 'oneTurn':10, 'lockBMin':1, 'min':1, 'wheelPad':2 } 1288 1289 self.widgetDescr['radius'] = { 1290 'class':'NEThumbWheel', 'master':'node', 'initialValue':1.0, 1291 'labelCfg':{'text':'radius:'}, 'width':80, 'height':20, 1292 'type':'float', 'oneTurn':10., 'lockBMin':1, 'min':0.1, 1293 'wheelPad':2 } 1294 1295 self.widgetDescr['headLength'] = { 1296 'class':'NEThumbWheel', 'initialValue':1., 1297 'labelCfg':{'text':'headLength:'}, 'width':80, 'height':20, 1298 'type':'float', 'oneTurn':10, 'lockBMin':1, 'min':0, 1299 'wheelPad':2 } 1300 1301 self.widgetDescr['headRadius'] = { 1302 'class':'NEThumbWheel', 'initialValue':2., 1303 'labelCfg':{'text':'headRadius:'}, 'width':80, 'height':20, 1304 'type':'float', 'oneTurn':10, 'lockBMin':1, 'min':0, 1305 'wheelPad':2 } 1306 1307 code = """def doit(self, coords=None, faces=None, colors=None, 1308 radius=None, quality=None, headLength=None, headRadius=None, 1309 image=None, 1310 name=None, geoms=None, instanceMatrices=None, geomOptions=None, parent=None): 1311 #print "doit", self.name 1312 GeometryNode.doit(self, name=name, geoms=geoms, 1313 instanceMatrices=instanceMatrices, 1314 geomOptions=geomOptions, parent=parent) 1315 1316 if coords is None: 1317 coords = [[0,0,0], [10,0,0]] 1318 faces = None 1319 1320 if faces is None: 1321 faces = [[0,1]] 1322 1323 if radius is None: 1324 radius = .6 1325 1326 if quality is None: 1327 quality = 15 1328 1329 if self.selectedGeomIndex is not None: 1330 g = self.geom() 1331 from opengltk.OpenGL import GL 1332 if colors is not None: 1333 inheritMaterial = False 1334 else: 1335 inheritMaterial = None 1336 g.Set(vertices=coords, faces=faces, materials=colors, tagModified=False, 1337 culling=GL.GL_NONE, inheritCulling=False, 1338 backPolyMode=GL.GL_FILL, inheritBackPolyMode=False, 1339 quality=quality, radii=radius, inheritMaterial=inheritMaterial) 1340 1341 GeometryNode.textureManagement(self, image=image) 1342 1343 self.outputData(axis=g, allGeometries=self.geoms) 1344 else: 1345 self.outputData(axis=None, allGeometries=self.geoms) 1346 """ 1347 if code: self.setFunction(code)
1348 1349
1350 - def appendGeometry(self, name):
1351 from DejaVu.Cylinders import CylinderArrows 1352 self.geoms.append(CylinderArrows(name)) 1353 return 1 # num of geoms appended
1354 1355 1356
1357 -class Spheres(GeometryNode):
1358 """Build a geometry for drawing a set of spheres. 1359 1360 The geometry nodes handle a list of geometries. When the name changes, 1361 a new geom is generated. If an empty name is provided, the current geometry 1362 is deleted. 1363 1364 The parent and children connections reflect the state of the geometry selected 1365 in the combo box. If the parent or children geoms are currently selected in 1366 their own node: the connections are present. If the parent or a child is not 1367 visible (for the selected geometry) the parent port or/and the output port 1368 contour lines are white (instead of black). Before parenting you can set the 1369 behaviour of the 'parent' inputport. Right clicking on the port allows you to 1370 extend the parenting to the sibling geometries present in the node or to all 1371 the geometries of the node. This behaviour set by right clicking will only 1372 affect the next parenting. In the same way, deleting the parent connection, 1373 reparent to 'root' the selected geometry or the sibling geometries or all the 1374 geometries in the child node (depending on the right click menu choice). 1375 1376 Input Ports: 1377 coords: Nx3 floating points values (type coordinates3D) 1378 colors: list of RGB tuples (optional) 1379 radius: float or list of floats of same length as coords (default is 1.0) 1380 quality: sphere quality, the hight, the more polygons are drawn (default 5) 1381 (bound to a Thumbwheel in node) 1382 name: name of the geometry 1383 instanceMatrices: stream of 4x4 transformation matrices (default identity) 1384 parent: a geometry to parent the selected geometry (default root) 1385 1386 Output Ports: 1387 Spheres: Spheres geometry 1388 allGeometries: list of all the geometries in the node 1389 """ 1390
1391 - def __init__(self, name='spheres', **kw):
1392 1393 kw['name'] = name 1394 apply( GeometryNode.__init__, (self,'spheres'), kw ) 1395 1396 ip = self.inputPortsDescr 1397 ip.append(datatype='coord3(0)', name='coords') 1398 ip.append(datatype='colorfloat3or4(0)', required=False, name='colors') 1399 ip.append(datatype='float(0)', required=False, name='radius') 1400 ip.append(datatype='int', required=False, name='quality') 1401 ip.append(datatype='image', required=False, name='image') 1402 1403 # for backward compatibility 1404 # this make sure that the first ports in the node are the ones 1405 # that use to be there before we introduced the GeometryNode class 1406 # (old network were saved with port indices instead of port names) 1407 self.rearrangePorts() 1408 1409 self.widgetDescr['quality'] = { 1410 'class':'NEThumbWheel', 'master':'node', 'initialValue':5, 1411 'labelCfg':{'text':'quality:'}, 'width':80, 'height':20, 1412 'type':'int', 'oneTurn':10, 'lockBMin':1, 'min':0, 'wheelPad':2 } 1413 1414 self.widgetDescr['radius'] = { 1415 'class':'NEThumbWheel', 'master':'node', 'initialValue':1.0, 1416 'labelCfg':{'text':'radius:'}, 'width':80, 'height':20, 1417 'type':'float', 'oneTurn':10., 'lockBMin':1, 'min':0.0000001, 1418 'wheelPad':2 } 1419 1420 code = """def doit(self, coords, colors=None, radius=1.0, quality=5, 1421 image=None, 1422 name=None, geoms=None, instanceMatrices=None, geomOptions=None, parent=None): 1423 #print "doit", self.name 1424 GeometryNode.doit(self, name=name, geoms=geoms, 1425 instanceMatrices=instanceMatrices, 1426 geomOptions=geomOptions, parent=parent) 1427 1428 try: 1429 len(radius) 1430 islist = True 1431 except TypeError: 1432 islist = False 1433 if islist: 1434 assert (len(radius)==1) or (len(radius)==len(coords)) 1435 1436 if self.selectedGeomIndex is not None: 1437 g = self.geom() 1438 if colors is not None: 1439 inheritMaterial = False 1440 else: 1441 inheritMaterial = None 1442 g.Set(vertices=coords, materials=colors, tagModified=False, 1443 radii=radius, quality=quality, inheritMaterial=inheritMaterial) 1444 1445 GeometryNode.textureManagement(self, image=image) 1446 1447 self.outputData(spheres=g, allGeometries=self.geoms) 1448 else: 1449 self.outputData(spheres=None, allGeometries=self.geoms) 1450 """ 1451 if code: self.setFunction(code)
1452 1453
1454 - def appendGeometry(self, name):
1455 from DejaVu.Spheres import Spheres 1456 self.geoms.append(Spheres(name)) 1457 return 1 # num of geoms appended
1458 1459 1460
1461 -class GeomContainer(GeometryNode):
1462 """Build a geometry that can be used as a container for other geometries. 1463 1464 The geometry nodes handle a list of geometries. When the name changes, 1465 a new geom is generated. If an empty name is provided, the current geometry 1466 is deleted. 1467 1468 The parent and children connections reflect the state of the geometry selected 1469 in the combo box. If the parent or children geoms are currently selected in 1470 their own node: the connections are present. If the parent or a child is not 1471 visible (for the selected geometry) the parent port or/and the output port 1472 contour lines are white (instead of black). Before parenting you can set the 1473 behaviour of the 'parent' inputport. Right clicking on the port allows you to 1474 extend the parenting to the sibling geometries present in the node or to all 1475 the geometries of the node. This behaviour set by right clicking will only 1476 affect the next parenting. In the same way, deleting the parent connection, 1477 reparent to 'root' the selected geometry or the sibling geometries or all the 1478 geometries in the child node (depending on the right click menu choice). 1479 1480 Input Ports: 1481 name: name of the geometry 1482 instanceMatrices: stream of 4x4 transformation matrices (default identity) 1483 parent: a geometry to parent the selected geometry (default root) 1484 1485 Output Ports: 1486 indexedPolygons: IndexedPolygons geometry 1487 allGeometries: list of all the geometries in the node 1488 """ 1489 """Set of polygons sharing vertices.""" 1490
1491 - def __init__(self, name='geomContainer', **kw):
1492 1493 kw['name'] = name 1494 apply( GeometryNode.__init__, (self,'geomContainer'), kw ) 1495 1496 #ip = self.inputPortsDescr 1497 1498 # for backward compatibility 1499 # this make sure that the first ports in the node are the ones 1500 # that use to be there before we introduced the GeometryNode class 1501 # (old network were saved with port indices instead of port names) 1502 # AS THERE IS NO INPUT PORT HERE, WE DON'T NEED TO CALL THIS 1503 #self.rearrangePorts() 1504 1505 code = """def doit(self, 1506 name=None, geoms=None, instanceMatrices=None, geomOptions=None, parent=None): 1507 #print "doit", self.name 1508 GeometryNode.doit(self, name=name, geoms=geoms, 1509 instanceMatrices=instanceMatrices, 1510 geomOptions=geomOptions, parent=parent) 1511 1512 if self.selectedGeomIndex is not None: 1513 g = self.geom() 1514 #g.Set( tagModified=False) 1515 self.outputData(geomContainer=g, allGeometries=self.geoms) 1516 else: 1517 self.outputData(geomContainer=None, allGeometries=self.geoms) 1518 """ 1519 if code: self.setFunction(code)
1520 1521
1522 - def appendGeometry(self, name):
1523 self.geoms.append(Geom(name)) 1524 return 1 # num of geoms appended
1525 1526 1527
1528 -class Ellipsoids(GeometryNode):
1529 """Build a geometry for drawing a set of Ellipsoids. 1530 1531 The geometry nodes handle a list of geometries. When the name changes, 1532 a new geom is generated. If an empty name is provided, the current geometry 1533 is deleted. 1534 1535 The parent and children connections reflect the state of the geometry selected 1536 in the combo box. If the parent or children geoms are currently selected in 1537 their own node: the connections are present. If the parent or a child is not 1538 visible (for the selected geometry) the parent port or/and the output port 1539 contour lines are white (instead of black). Before parenting you can set the 1540 behaviour of the 'parent' inputport. Right clicking on the port allows you to 1541 extend the parenting to the sibling geometries present in the node or to all 1542 the geometries of the node. This behaviour set by right clicking will only 1543 affect the next parenting. In the same way, deleting the parent connection, 1544 reparent to 'root' the selected geometry or the sibling geometries or all the 1545 geometries in the child node (depending on the right click menu choice). 1546 1547 Input Ports: 1548 ellipsoids: list of ellipsoid objects (can be generated using the EllipsoidFit node) 1549 colors: list of RGB tuples (optional) 1550 name: name of the geometry 1551 instanceMatrices: stream of 4x4 transformation matrices (default identity) 1552 parent: a geometry to parent the selected geometry (default root) 1553 1554 Output Ports: 1555 ellipsoids: Ellipsoids geometry 1556 allGeometries: list of all the geometries in the node 1557 """ 1558
1559 - def __init__(self, name='ellipsoids', **kw):
1560 1561 kw['name'] = name 1562 apply( GeometryNode.__init__, (self,'ellipsoids'), kw ) 1563 1564 ip = self.inputPortsDescr 1565 ip.append(datatype='list', name='ellipsoids') 1566 ip.append(datatype='colorfloat3or4(0)', required=False, name='colors') 1567 ip.append(datatype='image', required=False, name='image') 1568 1569 # for backward compatibility 1570 # this make sure that the first ports in the node are the ones 1571 # that use to be there before we introduced the GeometryNode class 1572 # (old network were saved with port indices instead of port names) 1573 self.rearrangePorts() 1574 1575 code = """def doit(self, ellipsoids, colors=None, 1576 image=None, 1577 name=None, geoms=None, instanceMatrices=None, geomOptions=None, parent=None): 1578 #print "doit", self.name 1579 GeometryNode.doit(self, name=name, geoms=geoms, 1580 instanceMatrices=instanceMatrices, 1581 geomOptions=geomOptions, parent=parent) 1582 1583 if ellipsoids is not None: 1584 centers = [] 1585 size = [] 1586 orient = [] 1587 for ellipse in ellipsoids: 1588 centers.append( ellipse.getPosition() ) 1589 size.append( ellipse.getAxis().astype('f') ) 1590 orint = identity(4, 'f') 1591 orint[:3, :3] = ellipse.getOrientation() 1592 orient.append( orint ) 1593 1594 if self.selectedGeomIndex is not None and ellipsoids is not None: 1595 g = self.geom() 1596 if colors is not None: 1597 inheritMaterial = False 1598 else: 1599 inheritMaterial = None 1600 g.Set(centers=centers, scaling=size, orientation=orient, 1601 materials=colors, tagModified=False, 1602 quality=30, inheritMaterial=inheritMaterial) 1603 1604 GeometryNode.textureManagement(self, image=image) 1605 1606 self.outputData(ellipsoids=g, allGeometries=self.geoms) 1607 else: 1608 self.outputData(ellipsoids=None, allGeometries=self.geoms) 1609 """ 1610 if code: self.setFunction(code)
1611 1612
1613 - def appendGeometry(self, name):
1614 from DejaVu.Ellipsoids import Ellipsoids 1615 self.geoms.append(Ellipsoids(name)) 1616 return 1 # num of geoms appended
1617 1618 1619
1620 -class Array2DToHeightFieldGeom(GeometryNode):
1621 """ convert a 2D array of values into a height field 1622 Input: 1623 data: 2Darray 1624 scaleZ: Z scaling factor 1625 Output 1626 geom: IndexedPolygons height field 1627 """ 1628
1629 - def __init__(self, name='heightField', **kw):
1630 1631 kw['name'] = name 1632 apply( GeometryNode.__init__, (self,'heightField'), kw) 1633 1634 ip = self.inputPortsDescr 1635 ip.append({'name': 'data', 'datatype': '2Darray'}) 1636 ip.append({'name': 'scaleZ', 'datatype': 'float'}) 1637 1638 self.rearrangePorts() 1639 1640 self.widgetDescr['scaleZ'] = { 1641 'class':'NEThumbWheel', 1642 'master':'node', 1643 'initialValue':1.0, 1644 'labelCfg':{'text':'scale Z:'}, 1645 'width':80, 'height':20, 1646 'type':'float', 'oneTurn':10., 'lockBMin':1, 'min':0.0, 1647 'wheelPad':2 } 1648 1649 code = """def doit(self, data, scaleZ=1.0, 1650 name=None, geoms=None, instanceMatrices=None, geomOptions=None, parent=None): 1651 #print "doit", self.name 1652 GeometryNode.doit(self, name=name, geoms=geoms, 1653 instanceMatrices=instanceMatrices, 1654 geomOptions=geomOptions, parent=parent) 1655 1656 if self.selectedGeomIndex is not None and data is not None: 1657 # normalize the data to range from 0 to 255 1658 maxi = max(data.flat) 1659 mini = min(data.flat) 1660 delta = maxi-mini 1661 data2 = (data-mini)/delta 1662 1663 verts = [] 1664 quads = [] 1665 sx, sy = data.shape 1666 for xi in xrange(sx): 1667 base = sx*xi 1668 for yi in xrange(sy): 1669 verts.append( (xi,yi,data[xi,yi]/scaleZ) ) 1670 if xi<sx-1 and yi<sy-1: 1671 quads.append( ( base+sx+yi, base+sx+yi+1, base+yi+1, 1672 base+yi )) 1673 1674 g = self.geom() 1675 g.Set(vertices=verts, faces=quads, tagModified=False) 1676 self.outputData(heightField=g, allGeometries=self.geoms) 1677 else: 1678 self.outputData(heightField=None, allGeometries=self.geoms) 1679 """ 1680 self.setFunction(code)
1681 1682
1683 - def appendGeometry(self, name):
1684 from DejaVu.IndexedPolygons import IndexedPolygons 1685 self.geoms.append(IndexedPolygons(name)) 1686 return 1 # num of geoms appended
1687 1688 1689
1690 -class GeomsFromFile(GeometryNode):
1691 """inheriting GeometryNode, this node reads several file formats, 1692 STL, OBJ, VERT ... and generates the correcponding geoms. 1693 the geom's names are deducted from the filename. 1694 you can easily add new file types to this node. 1695 """
1696 - def __init__(self, name='geomsFromFile', **kw):
1697 kw['name'] = name 1698 apply( GeometryNode.__init__, (self,'geomsFromFile'), kw ) 1699 1700 ip = self.inputPortsDescr 1701 ip.append(datatype='string', name='filename') 1702 ip.append(datatype='image', required=False, name='image') 1703 1704 self.rearrangePorts() 1705 1706 self.widgetDescr['filename'] = { 1707 'class':'NEEntryWithFileBrowser', 'master':'node', 'width':10, 1708 'initialValue':'', 1709 'labelCfg':{'text':'Filename: '}, 1710 'filetypes': [('stl','*.stl'), 1711 ('obj','*.obj'), 1712 ('vert','*.vert'), 1713 ('all', '*')]} 1714 1715 self.filenames = [] 1716 1717 code = """def doit(self, filename, 1718 image=None, 1719 name=None, geoms=None, instanceMatrices=None, geomOptions=None, parent=None): 1720 #print "doit", self.name 1721 lName = os.path.split(os.path.splitext(filename)[0])[-1] 1722 if filename not in self.filenames: 1723 self.filenames.append(filename) 1724 name = lName 1725 else: 1726 for g in self.geoms: 1727 if (g.name == lName) or g.name.startswith(lName + '+'): 1728 break 1729 else: #we didn't break 1730 if geoms == '': 1731 self.filenames.remove(filename) 1732 else: 1733 name = lName 1734 1735 GeometryNode.doit(self, name=name, geoms=geoms, 1736 instanceMatrices=instanceMatrices, 1737 geomOptions=geomOptions, parent=parent) 1738 1739 if self.selectedGeomIndex is not None: 1740 g = self.geom() 1741 #g.Set( tagModified=False ) 1742 1743 GeometryNode.textureManagement(self, image=image) 1744 1745 self.outputData(geomsFromFile=g, allGeometries=self.geoms) 1746 else: 1747 self.outputData(geomsFromFile=None, allGeometries=self.geoms) 1748 """ 1749 self.setFunction(code)
1750
1751 - def appendGeometry(self, name):
1752 filename = self.inputPortByName['filename'].getData() 1753 if filename is None or filename == '': 1754 return 1755 1756 # read the geoms from the file 1757 lExt = os.path.splitext(filename)[-1][1:].lower() 1758 if lExt == 'stl': 1759 moreGeoms = self.readFileSTL(filename) 1760 elif lExt == 'vert': 1761 moreGeoms = self.readFileIndexedPolygons(filename) 1762 elif lExt == 'obj': 1763 moreGeoms = self.readFileOBJ(filename) 1764 else: 1765 assert False 1766 1767 # append the geoms 1768 if moreGeoms is not None: 1769 for moreGeom in moreGeoms: 1770 self.geoms.append(moreGeom) 1771 1772 return len(moreGeoms) 1773 else: 1774 return 0
1775 1776
1777 - def nameGeoms(self, listOfGeoms, filename):
1778 """renames each geom differently 1779 """ 1780 if len(listOfGeoms) > 0: 1781 nameSplit = os.path.splitext(filename) 1782 name = os.path.split(nameSplit[0])[-1] 1783 listOfGeoms[0].name = name 1784 for i in range(1, len(listOfGeoms)): 1785 listOfGeoms[i].name = name + '+' + str(i)
1786 1787
1788 - def readFileSTL(self, filename):
1789 """from a filename, returns a list of geoms 1790 """ 1791 from DejaVu.DataInput import readAnySTL 1792 moreGeoms = readAnySTL(filename) 1793 return moreGeoms
1794 1795
1796 - def readFileIndexedPolygons(self, filename):
1797 """from a filename, returns a list of geoms 1798 """ 1799 from DejaVu.IndexedPolygons import IndexedPolygonsFromFile 1800 singleGeom = IndexedPolygonsFromFile(filename) 1801 moreGeoms = [ singleGeom ] 1802 self.nameGeoms(moreGeoms, filename) 1803 return moreGeoms
1804 1805
1806 - def readFileOBJ(self, filename):
1807 """from a filename, returns a list of geoms 1808 """ 1809 from DejaVu.DataInput import readOBJ 1810 moreGeoms = readOBJ(filename) 1811 return moreGeoms
1812 1813 1814 1815 1816 #class GlutLabelsNE(GeometryNode): 1817 # """Build a geometry for drawing a set of polygons sharing vertices. 1818 # 1819 #The geometry nodes handle a list of geometries. When the name changes, 1820 #a new geom is generated. If an empty name is provided, the current geometry 1821 #is deleted. 1822 # 1823 #The parent and children connections reflect the state of the geometry selected 1824 #in the combo box. If the parent or children geoms are currently selected in 1825 #their own node: the connections are present. If the parent or a child is not 1826 #visible (for the selected geometry) the parent port or/and the output port 1827 #contour lines are white (instead of black). Before parenting you can set the 1828 #behaviour of the 'parent' inputport. Right clicking on the port allows you to 1829 #extend the parenting to the sibling geometries present in the node or to all 1830 #the geometries of the node. This behaviour set by right clicking will only 1831 #affect the next parenting. In the same way, deleting the parent connection, 1832 #reparent to 'root' the selected geometry or the sibling geometries or all the 1833 #geometries in the child node (depending on the right click menu choice). 1834 # 1835 #Input Ports: 1836 # coords: Nx3 floating points values (type coordinates3D) 1837 # labels: list of labels ex:['label1', 'label2', 15.56, 'label4', 4, 5.78] 1838 # if one label only, it applies to all coords, 1839 # otherwise len(coords) should equal len(labels) 1840 # font: 1841 # colors: list of RGB tuples (optional) 1842 # name: name of the geometry 1843 # instanceMatrices: stream of 4x4 transformation matrices (default identity) 1844 # parent: a geometry to parent the selected geometry (default root) 1845 # 1846 #Output Ports: 1847 # indexedPolygons: IndexedPolygons geometry 1848 # allGeometries: list of all the geometries in the node 1849 #""" 1850 # 1851 # def __init__(self, name='glutlabels', **kw): 1852 # 1853 # kw['name'] = name 1854 # apply( GeometryNode.__init__, (self, 'glutlabels'), kw ) 1855 # 1856 # ip = self.inputPortsDescr 1857 # ip.append(datatype='coord3(0)', name='coords') 1858 # ip.append(datatype='string(0)', name='labels') 1859 # ip.append(datatype='colorfloat3or4(0)', required=False, name='colors') 1860 # ip.append(datatype='string', required=False, name='font') 1861 # 1862 # # for backward compatibility 1863 # # this make sure that the first ports in the node are the ones 1864 # # that use to be there before we introduced the GeometryNode class 1865 # # (old network were saved with port indices instead of port names) 1866 # self.rearrangePorts() 1867 # 1868 # self.widgetDescr['font'] = { 1869 # 'class':'NEComboBox', 1870 # 'master':'node', 1871 # 'entryfield_entry_width':14, 1872 # 'choices':[ 'glutTimesRoman10', 1873 # 'glut9by15', 1874 # 'glut8by13', 1875 # 'glutTimesRoman10', 1876 # 'glutTimesRoman24', 1877 # 'glutHelvetica10', 1878 # 'glutHelvetica12', 1879 # 'glutHelvetica18' 1880 # ], 1881 # 'initialValue':'glutTimesRoman10', 1882 # 'autoList':True, 1883 # 'labelCfg':{'text':'font:'}, 1884 # } 1885 # 1886 # self.widgetDescr['labels'] = { 1887 # 'class':'NEEntry', 'master':'node', 'width':10, 1888 # 'labelCfg':{'text':'labels:'}, 1889 # } 1890 # 1891 # code = """def doit(self, coords, labels, colors=None, font=None, 1892 #name=None, geoms=None, instanceMatrices=None, geomOptions=None, parent=None): 1893 # #print "doit", self.name 1894 # #apply( GeometryNode.doit, (self,)+args ) 1895 # GeometryNode.doit(self, name=name, geoms=geoms, 1896 # instanceMatrices=instanceMatrices, 1897 # geomOptions=geomOptions, parent=parent) 1898 # 1899 # if self.selectedGeomIndex is not None: 1900 # g = self.geom() 1901 # if colors is not None: 1902 # inheritMaterial = False 1903 # else: 1904 # inheritMaterial = None 1905 # import types 1906 # if type(labels) == types.StringType: 1907 # if len(labels): 1908 # labels = eval(labels) 1909 # if (labels is not None) and (labels != ''): 1910 # g.Set( inheritMaterial=inheritMaterial, 1911 # materials=colors, 1912 # tagModified=False, 1913 # visible=1, 1914 # labels=labels, 1915 # vertices=coords, 1916 # font=font) 1917 # else: 1918 # g.Set(visible=0) 1919 # self.outputData(glutlabels=g, allGeometries=self.geoms) 1920 # else: 1921 # self.outputData(glutlabels=None, allGeometries=self.geoms) 1922 #""" 1923 # if code: self.setFunction(code) 1924 # 1925 # 1926 # def appendGeometry(self, name): 1927 # from DejaVu.Labels import Labels 1928 # self.geoms.append( Labels(name=name, shape=(0,3) ) ) 1929 # return 1 # num of geoms appended 1930 1931 1932
1933 -class GlfLabelsNE(GeometryNode):
1934 """Build a geometry for drawing a set of polygons sharing vertices. 1935 1936 The geometry nodes handle a list of geometries. When the name changes, 1937 a new geom is generated. If an empty name is provided, the current geometry 1938 is deleted. 1939 1940 The parent and children connections reflect the state of the geometry selected 1941 in the combo box. If the parent or children geoms are currently selected in 1942 their own node: the connections are present. If the parent or a child is not 1943 visible (for the selected geometry) the parent port or/and the output port 1944 contour lines are white (instead of black). Before parenting you can set the 1945 behaviour of the 'parent' inputport. Right clicking on the port allows you to 1946 extend the parenting to the sibling geometries present in the node or to all 1947 the geometries of the node. This behaviour set by right clicking will only 1948 affect the next parenting. In the same way, deleting the parent connection, 1949 reparent to 'root' the selected geometry or the sibling geometries or all the 1950 geometries in the child node (depending on the right click menu choice). 1951 1952 Input Ports: 1953 coords: Nx3 floating points values (type coordinates3D) 1954 labels: list of labels ex:['label1', 'label2', 15.56, 'label4', 4, 5.78] 1955 if one label only, it applies to all coords, 1956 otherwise len(coords) should equal len(labels) 1957 font: 1958 colors: list of RGB tuples (optional) 1959 name: name of the geometry 1960 instanceMatrices: stream of 4x4 transformation matrices (default identity) 1961 parent: a geometry to parent the selected geometry (default root) 1962 1963 Output Ports: 1964 indexedPolygons: IndexedPolygons geometry 1965 allGeometries: list of all the geometries in the node 1966 """ 1967
1968 - def __init__(self, name='glflabels', **kw):
1969 1970 kw['name'] = name 1971 apply( GeometryNode.__init__, (self, 'glflabels'), kw ) 1972 1973 ip = self.inputPortsDescr 1974 ip.append(datatype='coord3(0)', name='coords') 1975 ip.append(datatype='string(0)', name='labels') 1976 ip.append(datatype='normal3(0)', required=False, name='vnormals') 1977 ip.append(datatype='colorfloat3or4(0)', required=False, name='colors') 1978 ip.append(datatype='boolean', required=False, name='billboard') 1979 ip.append(datatype='boolean', required=False, name='includeCameraRotationInBillboard') 1980 ip.append(datatype='string', required=False, name='font') 1981 ip.append(datatype='string', required=False, name='fontstyle') 1982 ip.append(datatype='float', required=False, name='fontSpacing') 1983 ip.append(datatype='float', required=False, name='scaleXYZ') 1984 ip.append(datatype='float', required=False, name='scaleX') 1985 ip.append(datatype='float', required=False, name='scaleY') 1986 ip.append(datatype='float', required=False, name='scaleZ') 1987 ip.append(datatype='float', required=False, name='fontRotateAngleX') 1988 ip.append(datatype='float', required=False, name='fontRotateAngleY') 1989 ip.append(datatype='float', required=False, name='fontRotateAngleZ') 1990 ip.append(datatype='float', required=False, name='fontTranslateX') 1991 ip.append(datatype='float', required=False, name='fontTranslateY') 1992 ip.append(datatype='float', required=False, name='fontTranslateZ') 1993 ip.append(datatype='image', required=False, name='image') 1994 1995 # for backward compatibility 1996 # this make sure that the first ports in the node are the ones 1997 # that use to be there before we introduced the GeometryNode class 1998 # (old network were saved with port indices instead of port names) 1999 self.rearrangePorts() 2000 2001 from DejaVu.glfLabels import GlfLabels 2002 self.widgetDescr['labels'] = { 2003 'class':'NEEntry', 2004 'master':'node', 2005 'initialValue':['Aa','Bb','Cc'], 2006 'width':10, 2007 'labelCfg':{'text':'labels:'}, 2008 } 2009 2010 self.widgetDescr['billboard'] = { 2011 'class':'NECheckButton', 2012 'master':'node', 2013 'initialValue':0, 2014 'labelCfg':{'text':'billboard:'}, 2015 } 2016 2017 self.widgetDescr['includeCameraRotationInBillboard'] = { 2018 'class':'NECheckButton', 2019 'master':'node', 2020 'initialValue':0, 2021 'labelCfg':{'text':'includeCameraRotationInBillboard:'}, 2022 } 2023 2024 self.widgetDescr['font'] = { 2025 'class':'NEComboBox', 2026 'master':'node', 2027 'entryfield_entry_width':14, 2028 'choices':GlfLabels.fontList, 2029 'initialValue':GlfLabels.fontList[0], 2030 'autoList':True, 2031 'labelCfg':{'text':'font:'}, 2032 } 2033 2034 self.widgetDescr['fontstyle'] = { 2035 'class':'NEComboBox', 2036 'master':'node', 2037 'entryfield_entry_width':14, 2038 'choices':GlfLabels.fontStyleList, 2039 'initialValue':GlfLabels.fontStyleList[3], 2040 'autoList':True, 2041 'labelCfg':{'text':'font style:'}, 2042 } 2043 2044 self.widgetDescr['fontSpacing'] = { 2045 'class':'NEDial', 2046 'master':'ParamPanel', 2047 'size':50, 2048 'oneTurn':1, 2049 'min':0., 2050 'max':1., 2051 'type':'float', 2052 'showLabel':1, 2053 'continuous':0, 2054 'initialValue':.2, 2055 'labelCfg':{'text':'fontSpacing'}, 2056 } 2057 2058 self.widgetDescr['scaleXYZ'] = { 2059 'class':'NEDial', 2060 'master':'ParamPanel', 2061 'size':50, 2062 'oneTurn':1, 2063 'min':0., 2064 'max':100., 2065 'type':'float', 2066 'showLabel':1, 2067 'continuous':0, 2068 'initialValue':1., 2069 'labelCfg':{'text':'scale XYZ'}, 2070 } 2071 2072 self.widgetDescr['scaleX'] = { 2073 'class':'NEDial', 2074 'master':'ParamPanel', 2075 'size':50, 2076 'oneTurn':1, 2077 'min':0., 2078 'max':100., 2079 'type':'float', 2080 'showLabel':1, 2081 'continuous':0, 2082 'initialValue':1., 2083 'labelCfg':{'text':'scale X'}, 2084 } 2085 2086 self.widgetDescr['scaleY'] = { 2087 'class':'NEDial', 2088 'master':'ParamPanel', 2089 'size':50, 2090 'oneTurn':1, 2091 'min':0., 2092 'max':100., 2093 'type':'float', 2094 'showLabel':1, 2095 'continuous':0, 2096 'initialValue':1., 2097 'labelCfg':{'text':'scale Y'}, 2098 } 2099 2100 self.widgetDescr['scaleZ'] = { 2101 'class':'NEDial', 2102 'master':'ParamPanel', 2103 'size':50, 2104 'oneTurn':1, 2105 'min':0., 2106 'max':100., 2107 'type':'float', 2108 'showLabel':1, 2109 'continuous':0, 2110 'initialValue':1., 2111 'labelCfg':{'text':'scale Z'}, 2112 } 2113 2114 self.widgetDescr['fontRotateAngleX'] = { 2115 'class':'NEDial', 2116 'master':'ParamPanel', 2117 'size':50, 2118 'oneTurn':90, 2119 'min':-180., 2120 'max':180., 2121 'type':'float', 2122 'showLabel':1, 2123 'continuous':0, 2124 'initialValue':0., 2125 'labelCfg':{'text':'font rotation angle X'}, 2126 } 2127 2128 self.widgetDescr['fontRotateAngleY'] = { 2129 'class':'NEDial', 2130 'master':'ParamPanel', 2131 'size':50, 2132 'oneTurn':90, 2133 'min':-180., 2134 'max':180., 2135 'type':'float', 2136 'showLabel':1, 2137 'continuous':0, 2138 'initialValue':0., 2139 'labelCfg':{'text':'font rotation angle Y'}, 2140 } 2141 2142 self.widgetDescr['fontRotateAngleZ'] = { 2143 'class':'NEDial', 2144 'master':'ParamPanel', 2145 'size':50, 2146 'oneTurn':90, 2147 'min':-180., 2148 'max':180., 2149 'type':'float', 2150 'showLabel':1, 2151 'continuous':0, 2152 'initialValue':0., 2153 'labelCfg':{'text':'font rotation angle Z'}, 2154 } 2155 2156 self.widgetDescr['fontTranslateX'] = { 2157 'class':'NEDial', 2158 'master':'ParamPanel', 2159 'size':50, 2160 'oneTurn':10, 2161 'min':-100., 2162 'max':100., 2163 'type':'float', 2164 'showLabel':1, 2165 'continuous':0, 2166 'initialValue':0., 2167 'labelCfg':{'text':'font translation X'}, 2168 } 2169 2170 self.widgetDescr['fontTranslateY'] = { 2171 'class':'NEDial', 2172 'master':'ParamPanel', 2173 'size':50, 2174 'oneTurn':10, 2175 'min':-100., 2176 'max':100., 2177 'type':'float', 2178 'showLabel':1, 2179 'continuous':0, 2180 'initialValue':0., 2181 'labelCfg':{'text':'font translation Y'}, 2182 } 2183 2184 self.widgetDescr['fontTranslateZ'] = { 2185 'class':'NEDial', 2186 'master':'ParamPanel', 2187 'size':50, 2188 'oneTurn':10, 2189 'min':-100., 2190 'max':100., 2191 'type':'float', 2192 'showLabel':1, 2193 'continuous':0, 2194 'initialValue':0., 2195 'labelCfg':{'text':'font translation Z'}, 2196 } 2197 2198 code = """def doit(self, coords, labels, vnormals=None, colors=None, 2199 billboard=None, includeCameraRotationInBillboard=None, font=None, fontstyle=None, 2200 fontSpacing=None, scaleXYZ=None, scaleX=None, scaleY=None, scaleZ=None, 2201 fontRotateAngleX=None, fontRotateAngleY=None, fontRotateAngleZ=None, 2202 fontTranslateX=None, fontTranslateY=None, fontTranslateZ=None, 2203 image=None, 2204 name=None, geoms=None, instanceMatrices=None, geomOptions=None, parent=None): 2205 #print "doit", self.name 2206 #apply( GeometryNode.doit, (self,)+args ) 2207 GeometryNode.doit(self, name=name, geoms=geoms, 2208 instanceMatrices=instanceMatrices, 2209 geomOptions=geomOptio