Magnets.py
1    try:
2        import poser
3    except ImportError:
4        from PoserLibs import POSER_FAKE as poser
5    
6    import WXtools
7    
8    reload(WXtools)
9    from WXtools import *
10   
11   SCENE = poser.Scene()
12   
13   
14   class Deformer(object):
15       __slots__ = ("mag",  # the magnet -
16                    "base",  # its base -
17                    "zones",  # and the zones.
18                    )
19   
20       def __init__(self, mag, base, zones):
21           self.mag = mag
22           self.base = base
23           self.zones = zones
24   
25   
26   def getMagnetSet(ac_or_name):
27       if isinstance(ac_or_name, basestring):
28           ac = SCENE.actor(ac_or_name)
29       else:
30           ac = ac_or_name
31   
32       base = mag = zone = None
33       if ac.IsBase():
34           base = ac
35           mag = base.Children()[0]
36       elif ac.IsDeformer():
37           mag = ac
38           base = mag.Parent()
39       elif ac.IsZone():
40           zone = ac
41           common_name = zone.Name()[:-1]
42           for p in ac.Parent().Children():
43               if p.Name().startwith(common_name):
44                   if p.Name()[-1] == "B":
45                       base = p
46                   elif p.Name()[-1] == "M":
47                       mag = p
48   
49       return mag, base
50   
51   
52   def collectMagnets(base=SCENE):
53       ar = list()
54       for ac in base.Actors():
55           if ac.IsDeformer():
56               ar.append(ac.InternalName())
57   
58   
59   def CreateMagnet(name, parent=None):
60       for ac in SCENE.Actors():  # type: poser.ActorType
61           if ac.IsDeformer() and ac.Name() == name:
62               return getMagnetSet(ac)
63   
64       ac = SCENE.CurrentActor()
65   
66       if isinstance(parent, poser.ActorType):
67           SCENE.SelectActor(parent)
68       else:
69           parent = ac
70   
71       mag = SCENE.CreateMagnet()  # type: poser.ActorType
72       oldname = mag.Name()
73       zone = mag.Zones()[0]
74       base = mag.Parent()
75   
76       mag.SetName(name + "_Mag")
77       base.SetName(name + "_Base")
78       if len(mag.Zones()) > 1:
79           for idx, z in enumerate(mag.Zones()):
80               zone.SetName(name + "_(%d)Zone" % idx)
81       else:
82           mag.Zones()[0].SetName(name + "_Zone")
83       for p in parent.Parameters():  # type: poser.ParmType
84           if (not p.Name().strip()) or p.Name().startswith(oldname):
85               p.SetName(name)
86   
87       SCENE.SelectActor(ac)
88       return mag, base
89   
90   
91   def getActorList(unfiltered=False, withgeometry=False, isbodypart=False):
92       def excluded(ac):
93           if unfiltered:
94               return False
95           if withgeometry:
96               if ac.Geometry() is None \
97                       or ac.Geometry().NumVertices() == 0:
98                   return True
99           if isbodypart and not ac.IsBodyPart():
100              return True
101          return ac.IsDeformer() or ac.IsBase() or ac.IsZone() or \
102                 ac.IsCamera() or ac.IsControlProp() or ac.IsLight() or \
103                 ac.IsMeasurement()
104  
105      return sorted([ac.Name() for ac in SCENE.Actors()
106                     if not excluded(ac)],
107                    key=lambda a: a[0].upper() + a[1:])
108  
109  
110  class MagnetDialog(wx.Dialog):
111      def __init__(self, *args, **kwargs):
112          wx.Dialog.__init__(self, *args, **kwargs)
113          self.gb_manager = GridBagManager(parent=self,
114                                           sizer=wx.GridBagSizer(0, 0),
115                                           flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND,
116                                           border=2
117                                           )
118          self.SetBackgroundColour(BG_COLOR)
119          self.SetForegroundColour(FG_COLOR)
120  
121          self.dialogitems = self.gb_manager.widgets
122  
123          f = wx.Font(SYS_FONT.GetPointSize() + 2, family=SYS_FONT.GetFamily(),
124                      style=SYS_FONT.GetStyle(), weight=wx.BOLD)
125          headline = PrepCtrl(wx.StaticText, id=-1, label="Magnet Utility", font=f)
126  
127          self.InitUI(self.gb_manager)
128  
129          main_sizer = wx.BoxSizer(wx.VERTICAL)
130          main_sizer.Add(headline, 0, wx.ALL | wx.ALIGN_LEFT, 5)
131          main_sizer.AddStretchSpacer(0)
132          main_sizer.Add(self.gb_manager.sizer, 1, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, 5)
133          btn_sizer = ButtonRow(wx.Button(self, id=wx.ID_OK),
134                                wx.Button(self, id=wx.ID_CANCEL))
135          main_sizer.Add(btn_sizer, 0, wx.ALL | wx.ALIGN_CENTER, 5)
136  
137          self.SetAutoLayout(True)
138          self.SetSizer(main_sizer)
139          main_sizer.Fit(self)
140  
141          self.Bind(wx.EVT_WINDOW_DESTROY, self.onClose)
142          self.Bind(wx.EVT_SIZE, self.onSize)
143  
144      def get_item_by_name(self, *args):
145          return self.gb_manager.get_item_by_name(*args)
146  
147      def onClose(self, ev):
148          ev.Skip()
149  
150      def onSize(self, ev):
151          ev.Skip()
152  
153      def onCheckBox(self, ev):
154          ev.Skip()
155  
156      def onChoice(self, ev):
157          ev.Skip()
158          return
159  
160          obj = ev.GetEventObject()  # type: wx.Choice
161          idx = obj.GetSelection()
162          name = str(obj.GetString(idx))
163          c = name[0]
164          comp = "LR" if c.isupper() else "lr"
165          opposite = comp[c[0].lower() == "l"] + name[1:]
166          try:
167              idx = getActorList().index(opposite)
168          except IndexError:
169              idx = None
170  
171          print("OPPOSITE", opposite if idx is not None else "None")
172  
173          obj = self.FindWindowByName("makepair")
174          if obj:
175              obj.SetValue(idx is not None)
176  
177      def InitUI(self, gbm):
178          actorlist = getActorList(unfiltered=True)
179          actoridx = actorlist.index(SCENE.CurrentActor().Name())
180  
181          # Attribute "key" is actually exchanged with "name".
182          # Using "key" makes clear it is the key used in the
183          # dictionary with results (after dialog is closed).
184          gbm.addrows(
185                  Labeled(wx.Choice, label="Actor", key="actor",
186                          choices=actorlist, index=actoridx,
187                          tooltip="Create new magnet in this actor",
188                          bind=(wx.EVT_CHOICE, self.onChoice)),
189                  Labeled(wx.TextCtrl, label="Name", key="Magname",
190                          tooltip="New magnets name"),
191                  Labeled(wx.TextCtrl, label="Base Size %", key="b_size", style=wx.TE_RIGHT,
192                          value="15", tooltip="Size of base control in percent"),
193                  Labeled(wx.TextCtrl, label="Zone Size %", key="z_size", style=wx.TE_RIGHT,
194                          value="10", tooltip="Size of Zone control in percent"),
195                  Labeled(wx.CheckBox, label="Zone Wireframe", key="wframe", style=wx.ALIGN_RIGHT,
196                          value=True, tooltip="Check to set zones displaystyle to wireframe"),
197                  None,  # an empty row
198                  Labeled(wx.CheckListBox, label="Affected Actors", key="affected",
199                          choices=getActorList(withgeometry=True),
200                          tooltip="Select actors affected by this deformer."),
201                  #                Labeled(wx.CheckBox, label="Create Pair", key="makepair", style=wx.ALIGN_RIGHT,
202                  #                        value=False, tooltip="Make another magnet at the other side"),
203  
204          )
205  
206          gbm.bindCtrls(wx.CheckBox, wx.EVT_CHECKBOX, self.onCheckBox)
207  
208  
209  with MagnetDialog(None, -1, style=wx.DEFAULT_DIALOG_STYLE) as dlg:
210      res = dlg.ShowModal()
211      if res == wx.ID_OK:
212          data = dlg.gb_manager.items_as_dict()
213          magname = data["Magname"]
214          #print("Mag Name:", magname)
215          #print("Actor:", data["actor"])
216          #print("Affected:", data["affected"])
217  
218          if magname.strip() and SCENE.Actor(data["actor"]):
219              ac = SCENE.Actor(data["actor"])
220              SCENE.SelectActor(ac)
221              mag, base = CreateMagnet(name=magname)
222              if data["wframe"]:
223                  [z.SetDisplayStyle(poser.kDisplayCodeWIREFRAME) for z in mag.Zones()]
224              v = int(data["b_size"])
225              if v:
226                  base.SetParameter("Scale", v / 100.0)
227              v = int(data["z_size"])
228              if v:
229                  [z.SetParameter("Scale", v / 100.0) for z in mag.Zones()]
230  
231              mag.SetMagnetAffectedObjects([SCENE.Actor(objname)
232                                            for objname in data.get("affected", [])] + [ac,])
233  
234              # rename Parameter names in affected actors
235              for actor in mag.MagnetAffectedObjects():
236                  for p in actor.Parameters():
237                      if p.Name().startswith(mag.Name()):
238                          p.SetName(magname)
239                          break
240