import poser import wx, wx.aui, wx.py import uu, zlib from StringIO import StringIO from array import array # somehow the builtin icons do not seem to be present in poser. # This block contains some 24x24 jpgs, encoded with uuencode. data_map = { 'visible': 'begin 666 -\nM_]C_X 02D9)1@ ! 0$ 2 !( #_VP!# 4#! 0$ P4$! 0%!04&!'\ + 'PP(!P<\'\nM!P\\+"PD,$0\\2$A$/$1$3%AP7$Q0:%1$1&"$8&AT=\'Q\\?$Q'\ + ')!P>\'Q[_\nMP +" 8 !@! 1$ _\\0 &0 @,! !P@$!08)_'\ + '\\0 )Q \nM 00" 0,#!0$ 0(#! 4&$0< "!(3(2(4,4%1@17_V@ ( 0$ '\ + ' #\\ \nMWW,7=\'6<>XJ='\ + "A3J\nMZ]^JMYKK];DTYX.^#94DEIMM302L) 4-^7MY>P '3)(9U97*>F2##]-MAUM/S#@V?$J*21K:?<#>STLG%.7K[>N6;@\\MX3(F9#9%,A5\nM'\ + 'FS)9>>C(<\\RM2 /BKU"KY:6D_\'6NHF:2.)K9J"RYSC<3<6K))D0,=1CCPD1D\nM*5'\ + 'M32\'5>+>QO04HZUU78[=V&4]R=9<\\&XJC$9,A16S!,M+;$IM!*G24GQ2E"\nMD)/D'\ + 'TC8\'B=>_70&UPG$+6[7=6F-UD^P<8$=;TF.EPJ;\'N$D*V"/YT*H/:UQD\nMG&GZ6Q'\ + "B+F*=M/]!,U#33,EL?A@.)3OTM$[3_ 'V(&C+&HJ2+(B2(U/7L/0V2\n3Q%<;C(2IAL"\ + '_=""!M*3^AH=?_V0 \n \nend\n', 'invisible': 'begin 666 -\nM_]C_X 02D9)1@ ! 0$ 2 !( #__@ H($-214%43U(Z($=)35 @4'\ + "$Y-($9I\nM;'1E)!P>\'Q[_'\ + 'P +\nM" 8 !@! 1$ _\\0 %@ ! 0$ !P@ _\\0 )A @$#! '\ + '$$\nM P$ 0(#! 41 8\'$@@3(5&!%3%!8?_: @! 0 /P"R];6U&NT_'\ + "\nM(OD'B*^/LGG6RU=TJ%].6*NIYH&GAA* $)A)AD9[%@^2V2WL Q0^4W!;PH[\nM;"\ + 'U>)F4$H]JK.RGX.(B,C_"1H=W)Y#[UY8Y"VUM;AZS5-H$5>*])[A5K#)<8X\nMXSWC='\ + ' W01#,I9>TA;HA\'4KC55779.T+K>WO5TVW;*^X20"G>:IIUD+1CW"D-\nMD$?6BJA'\ + '\\6N,EVU/9;C2/6-+=/R"UJ110U,8_D D5<^E@G*_?L0,,M-8K)2U%\n;)44UGM\\$U'\ + '\'"8*62.F16@C/[1"!E5/P,#7__9\n \nend\n', 'actor': 'begin 666 -\nM_]C_X 02D9)1@ ! 0$ 2 !( #__@ 30W)E871E9"!W:71H($=)3'\ + '5#_VP!#\nM 4#! 0$ P4$! 0%!04&!PP(!P<\'!P\\+"PD,$0\\2$A$/$1$3%AP7$Q'\ + '0:%1$1\nM&"$8&AT=\'Q\\?$Q)!P>\'Q[_P +" 8 !@! 1$ _\\0 & ! 0'\ + ' # \nM " 4"!@?_Q E$ !! $$ 00# ! @,$!1$&!Q'\ + '(A\nM !,B,4$(88/_V@ ( 0$ #\\ [9:[FS[35%A44CK-=&KWW(ZE.-I5)D+:<*7%'\ + '\nM(!)2&LX&<$G.;F$2(JP/CDA7N3_-22?WYLWX\nM'\ + "][K6.Z%=8R+'23U 87I!MTR?6:F.ZX\\S\nM"\ + '.B(]%U7,\\PM/2LG.3D@Y\\PABPW.UY,H[^Z1!K*A*5A#0"%.@MH45=G\'+*SWC\nM '\ + ' Z\'SXA=JV68E1!K-(6+"">*\n$OKS_V0 '\ + '\n \nend\n', 'add': 'begin 666 -\nM_]C_X 02D9)1@ ! 0$ 2 !( #__@ 30W)E871E9"!W:71H($=)3'\ + '5#_VP!#\nM 4#! 0$ P4$! 0%!04&!PP(!P<\'!P\\+"PD,$0\\2$A$/$1$3%AP7$Q'\ + '0:%1$1\nM&"$8&AT=\'Q\\?$Q)!P>\'Q[_P +" 8 !@! 1$ _\\0 %@ ! 0'\ + '$ \nM !P@&_\\0 *A 4"!0,$ P$ 0(#! 4\'$0 &'\ + '"!(A\nM$S%1%!5!L2(RP6\'_V@ ( 0$ #\\ HRM=4X2F$"D[?(K2$H]/THZ-;\\JN5'\ + '/X7\nMR/W@(:Z@JXN:A.\\JI9 RR+]HR!\\K$B9<\'0)"4I[ INVB;:IN6:$E64;41I'@H[<$43(FFCT4P $A3%N)%$P[=Q\n"\ + 'MY$,;C2P?.K;55(,\\U>E-*C%J%F#MC)F RA1_ 3BF.S[S&#Q\'J\nMJH%'\ + " H COW!P0@7!.X[2WO8,/NG&B[2EL4Y?2+P);-$F.^0?B' ?.P@CS:_<\n&1[CXQ__"\ + '9\n \nend\n', 'delete': 'begin 666 -\nM_]C_X 02D9)1@ ! 0$ 2 !( #__@ 30W)E871E9"!W:71H($=)3'\ + '5#_VP!#\nM 4#! 0$ P4$! 0%!04&!PP(!P<\'!P\\+"PD,$0\\2$A$/$1$3%AP7$Q'\ + '0:%1$1\nM&"$8&AT=\'Q\\?$Q)!P>\'Q[_P +" 8 !@! 1$ _\\0 & P'\ + '$! \nM !@<("07_Q J$ ! P(%! (!!0 ! @,$!1$ !@'\ + '<2\nM(0@3(C$406$8(V-QD?_: @! 0 /P#H=1NOFJFEVM1@M4Z(K*X2A49E^-XS\n'\ + 'M$;1O(=\'(4"2.#QP2#?!S^K+356F3F:DKD)JB5=D4-5ODEZUQZ-NW_)Z^K7XP\nMK='\ + '(.I7574/6^BT>/3H"*)*D)1*A1HV[LL7\\G5.&ZK@?=P#ZMSBBNI5W)$;2*\nMM3,]4'\ + 'V#4H4>.MR-&D+V*=D6(;2VH>25$D"Z>0"<9:J0I25/I:*6M]B0#M23<\nM@7_H\'_,:'\ + '>=)\\/)3>B="GY*IPB1Y;),I3A"WU/A12X\'%@#<0H&W %K6 &)LZ^\nM7LXYCUBHV4'\ + '85.GR*>S$0:>PRT5"0^X?W%"WLBR4_@#\\G#9JO3/2D],Z\\D4QI\nM"E "DW\'I!!4@#Z!!Y-\\"G0/0=3\\J9DS%0\\RY=K-(RZN-WD_\n5/BK:2986A([9'\ + '4!NNC?)!P>\'Q[_P +" 8 !@! 1$ _\\0 %@ ! 0'\ + '$ \nM " 8)_\\0 +! 0,"! 0$!P 0(#! 4& <1$'\ + '@@A\nM,4$3%2)A%"-14G%R@?_: @! 0 /P!$GTEQ.NNF[=NU\nM['\ + 'GIC1C$;G.Q6G:S\\Q+AS.+U\nM"3!A'\ + '2OB*LR_&2[+2ATK5NCZIU02KEJ"/H>6$)0K:I1 !\nMW)1J">:=P'\ + '[X/3.4&9V15]T*X[&HR[K@5*$S"K$%IDNC<4H\\="QV05I*DKZ)Z\nB\'W4=(L/R[,Z'\ + '7 0: def remove_if_fail (id): name = self.GetItemText (id) if name in fail_set: self.Delete (id) self.apply_leaf (remove_if_fail) class MainWindow (wx.Frame): def __init__ (self, parent = None): super (MainWindow, self).__init__\ (parent, style = wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT) vbox = wx.BoxSizer (wx.VERTICAL) self.SetSizer (vbox) self.SetAutoLayout (1) toolbar = wx.Panel (self) self.fill_toolbar (toolbar) self.tree = GroupTree (self) vbox.Add (toolbar, proportion = 0, flag = wx.EXPAND) vbox.Add (self.tree, proportion = 1, flag = wx.EXPAND) vbox.Fit (self) def fill_toolbar (self, toolbar): """initialize the toolbar (which is a simple panel) with buttons. """ hbox = wx.BoxSizer (wx.HORIZONTAL) toolbar.SetSizer (hbox) button_data = [ ('add', self.evt_add_group, 'Add a new group'), ('figure', self.evt_add_figure, 'Add the figure to groups'), ('actor', self.evt_add_actor, 'Add the actor/prop to groups'), ('delete', self.evt_del_object, 'Remove selected items from group'), ('invisible', self.evt_invis, 'Make selected items invisible'), ('visible', self.evt_vis, 'Make selected items visible'), ] for (id, (name, func, tip)) in enumerate (button_data): bmp = decode_img (data_map[name]) button = wx.BitmapButton (toolbar, id, bmp, name = name) button.SetToolTipString (tip) hbox.Add (button) self.Bind (wx.EVT_BUTTON, func, id = id) # definition of event callbacks. def evt_add_group (self, ev): default_idx = 1 while self.tree.group_exists ("group %d" % default_idx): default_idx += 1 default_name = "group %d" % default_idx dlg = wx.TextEntryDialog\ (self, "Give your group a name:", "Enter name", default_name) dlg.ShowModal () name = dlg.GetValue () self.tree.add_group (name) def evt_add_figure (self, ev): fig = poser_connect.get_figure_name () if fig is not None: self.tree.add_item (fig) def evt_add_actor (self, ev): act = poser_connect.get_actor_name () if act is not None: self.tree.add_item (act) def evt_del_object (self, ev): self.tree.del_item () # make visible/invisble # these perform the actual operations def evt_invis (self, ev): self.tree.map_items (lambda i: poser_connect.change_visibility (0, i)) poser_connect.update () def evt_vis (self, ev): self.tree.map_items (lambda i: poser_connect.change_visibility (1, i)) poser_connect.update () class poser_iface: """facade object for all used poser functions. """ def update (self): """redraw the scene after some modification was done. """ scene = poser.Scene () scene.Draw () def get_figure_name (self): """return the name of the current figure or none. """ figure = poser.Scene ().CurrentFigure () if figure is not None: return "F:" + figure.InternalName () else: return None def get_actor_name (self): """return the name of the current actor or none. Appends an 'A:' in front of the name, to distinguish it from figures. """ actor = poser.Scene ().CurrentActor () if actor is not None: return "A:" + actor.InternalName () else: return None def change_visibility (self, onoff, name): """change the visibility of the figure/actor with the given name. If the figure is not defined (might be erased from the scene), this function returns False. """ if poser: if name.startswith ("A:"): internal_name = name[2:] try: actor = poser.Scene ().ActorByInternalName (internal_name) except: actor = None if actor is not None: actor.SetOnOff (onoff) return True else: return False elif name.startswith ("F:"): internal_name = name[2:] # search the Scene for the figure. The scene does # not seem to have a findbyinternalname() method. for figure in poser.Scene ().Figures (): if figure.InternalName () == internal_name: figure.SetOnOff (onoff) return True return False else: # what is this? return False class noposer_iface: """facade object to be used when no poser available. """ def update (self): print ("redraw.") def get_figure_name (self): return "F:
" def get_actor_name (self): return "A:" def change_visibility (self, onoff, name): # dummy code for testing without poser print ("change visibility for %s to %d" % (name, onoff)) if __name__ == '__main__': if poser: aui = poser.WxAuiManager () root_window = aui.GetManagedWindow () poser_connect = poser_iface () else: app = wx.App () poser_connect = noposer_iface () root_window = None mwin = MainWindow (root_window) mwin.tree.add_group ("plushies") mwin.Show () if not poser: app.MainLoop ()