1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
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
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
94
95 self.selectedGeomIndex = None
96 self.geoms = []
97
98
99 ip = self.inputPortsDescr
100
101
102
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
109
110 ip.append(datatype='geomOrInsert2d', required=False, name='parent',
111 singleConnection=True)
112
113
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
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
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
157 op[0]['afterDisconnect'] = codeAfterDisconnectChildren
158
159
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
169
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:
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
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
199 self.reparentGeomType(
200 self.inputPortByName['parent'].cascadeMenuVariable.get(),
201 reparentCurrent=True)
202 else:
203 pass
204 else:
205 self.naming(geoms)
206
207
208
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
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
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
242 ip = self.inputPortsDescr
243 if len(ip) > self.numOfBaseClassInputPorts:
244 self.inputPortsDescr = ip[self.numOfBaseClassInputPorts:] \
245 + ip[:self.numOfBaseClassInputPorts]
246
247
249
250 assert self.selectedGeomIndex is not None
251
252
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
273
274
276
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
302
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
320
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
339
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
353
354
356 """returns the index of the geom
357 returns -1 if entry is not in the list
358 """
359
360
361 for i in range(len(self.geoms)):
362 if name == self.geoms[i].name:
363 return i
364 return -1
365
366
368 """ returns True if we need to perform Parenting
369 """
370
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
384
385 if w.size() == 0:
386 return False
387
388 if self.selectedGeomIndex is None:
389
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
401
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
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
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
432 self.geom().Set(name=name)
433 self.rename(self.geom().name)
434 return False
435
436
438
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
456 assert False, name
457 pass
458
459
461
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
481 self.selectedGeomIndex = None
482 self.inputPortByName['name'].widget.set(self.name, run=0)
483 self.rename("the list is empty")
484
485
487 """ prepare the parenting and launch it if applicable
488 it will parent the selectedGeomIndex unless geom is provided
489 """
490
491
492
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
509
510 elif isinstance(parent, list):
511 if len(parent) > 0 and hasattr(parent[0], 'node'):
512
513 parent = parent[0].node().geom()
514
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
523
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'
528
529 return 'Go'
530
531
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
538
539 if geom is None:
540 geom = self.geom()
541
542 if geom.viewer is None:
543 geom.parent = lParent
544 geom.fullName = geom.BuildFullName()
545 return True
546
547 if lParent is None:
548 lParent = geom.viewer.rootObject
549
550
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
559 name = geom.viewer.ensureUniqueName(geom.name, lParent, local=False, exclude=geom)
560
561
562
563
564 geom.name = name
565
566 geom.viewer.ReparentObject(geom, lParent)
567
568 self.ensureNameOfNodeAndDescendants(lHighestModifiedParent)
569
570
571
572
573
574 return True
575
576
578 """ finds the selected children and parent
579 and draws the connections if they are selected in their own node
580 """
581
582
583 if self.selectedGeomIndex is None:
584 return
585
586
587 self.removeParentConnection()
588
589
590 self.removeChildrenConnections()
591
592
593 self.setParentConnection()
594
595
596 self.setChildrenConnections()
597
598
600 """ set the parent connection if parent is selected in his own node
601 """
602
603
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
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
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:
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
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:
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
679
680
681 else:
682 lParentPort.hasHiddenConnections = True
683 else:
684
685
686
687
688
689
690
691
692
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
705
706
707 lParentPort = self.inputPortByName['parent']
708 for c in lParentPort.connections[::-1]:
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:
731 assert "weird! we should have found the port _parent"
732 lConnections = lMacroNode.inputPortByName[lPortNameInMacro].connections
733 if len(lConnections) > 0:
734
735 lMacroNetwork.deleteConnectionsNoCB(lConnections[0])
736 else:
737
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
750
751 for lChild in self.geom().children:
752 if hasattr(lChild, 'node'):
753 if lChild == lChild.node().geom():
754 lChild.node().setParentConnection()
755
756 self.setPortsOfTheChildrenConnections()
757
758
760
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
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
780
781 for lChild in self.geom().children:
782 if hasattr(lChild, 'node'):
783 if lChild == lChild.node().geom():
784 lChild.node().removeParentConnection()
785
786
788 """ """
789
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
807
808
809 parent = self.inputPortByName['parent'].getData()
810
811 for g in list:
812 self.parenting(parent,g)
813
814
816
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
827 for g in self.geoms:
828 if g is not geom or reparentCurrent is True:
829
830
831 if g.parent is geom.parent:
832 lGeomsToReparent.append(g)
833 elif type == 'all':
834
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
845
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
858
859
860
861
862
863
864
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
874
875
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
896
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
907
908
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
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
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
998
999
1000
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
1038
1039
1040
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
1087
1088
1089
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
1124
1125
1126
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
1176
1177
1178
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
1223
1224
1225
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
1279
1280
1281
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
1354
1355
1356
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
1404
1405
1406
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
1458
1459
1460
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
1497
1498
1499
1500
1501
1502
1503
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
1525
1526
1527
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
1570
1571
1572
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
1617
1618
1619
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
1687
1688
1689
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
1752 filename = self.inputPortByName['filename'].getData()
1753 if filename is None or filename == '':
1754 return
1755
1756
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
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
1794
1795
1804
1805
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
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
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
1996
1997
1998
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