from __future__ import print_function try: import poser except ImportError: raise RuntimeError("Script must run in Poser.") import wx import wx.aui import sys import os import time import json import numpy as NP from shutil import copyfile CONFIG = dict() BASEPATH = os.path.abspath(os.path.dirname(sys.argv[0])) SCRIPT_FILENAME = os.path.basename(sys.argv[0]) CONFIG_FILENAME = SCRIPT_FILENAME.rsplit(".")[0] + ".cfg" # Forced floatingpoint precision. Mainly to help avoiding floatingpoint # errors while reading files from external modelers. PRECISION = 8 NP_PRECISION = NP.float32 def ErrDialog(err, msg=None): dlg = wx.MessageDialog(None, caption=err, message=msg, style=wx.ICON_ERROR) dlg.ShowModal() dlg.Close() def read_config(): global CONFIG fname = os.path.join(BASEPATH, CONFIG_FILENAME) if os.path.isfile(fname): try: with open(fname, "r") as fh: CONFIG = json.load(fh, encoding="utf-8") except IOError: pass def write_config(): global CONFIG fname = os.path.join(BASEPATH, CONFIG_FILENAME) try: with open(fname, "w") as fh: json.dump(CONFIG, fh) except IOError: ErrDialog("File Error.", "Can't write configfile '{}.".format(fname)) def find_parms_with_name(parmname): """ Return dict with actornames as key an parameter as content. :param parmname: :return: """ assert isinstance(parmname, basestring) actor_dict = dict() for actor in poser.Scene().Actors(): ac_name = actor.Name() for parm in actor.Parameters(): if parm.Name() == parmname: actor_dict[ac_name] = parm return actor_dict def write_matfile(filename, materials): """ Write out a simple material-file. """ def move_image(map2move): fname = os.path.join(CONFIG.get("MatPath", "."), os.path.basename(map2move)) if os.path.exists(fname): if os.path.getmtime(map2move) == os.path.getmtime(fname): copyfile(map2move, fname) else: copyfile(map2move, fname) return fname try: tmp = open(filename, "w") tmp.close() except IOError: return ErrDialog("File Error.", "Can't create or write to file '{}'.\n" "Make sure directory '{}' exist and is writable.". format(filename, os.path.dirname(filename))) with open(filename, "w") as mfh: for mat in materials: print("newmtl", mat.Name(), file=mfh) print("Ns", mat.Ns(), file=mfh) print("Ka", "0 0 0", file=mfh) print("Kd", " ".join(map(str, mat.DiffuseColor())), file=mfh) print("Ks", "0 0 0", file=mfh) if mat.TextureMapFileName(): texmap = mat.TextureMapFileName() if CONFIG.get("CTRL_MoveTextures", False): texmap = move_image(texmap) print("map_Kd", texmap, file=mfh) if mat.BumpMapFileName(): texmap = mat.BumpMapFileName() if CONFIG.get("CTRL_MoveTextures", False): texmap = move_image(texmap) print("map_Bump", texmap, file=mfh) def collect_geometry(figure): if figure is None: return None def np_vertex(v): return NP.array((v.X(), v.Y(), v.Z()), NP_PRECISION) geom, actorlist, actor_indices = figure.UnimeshInfo() verts = NP.zeros((geom.NumVertices(), 3), NP_PRECISION) for actor_idx, actor in enumerate(actorlist): world_verts = actor.Geometry().WorldVertices() for i, vertex_idx in enumerate(actor_indices[actor_idx]): verts[vertex_idx] = np_vertex(world_verts[i]) return dict(vertices=verts, geom=geom, actorlist=actorlist, actor_indices=actor_indices, ) def read_vertices(filename): """ Read Wavefront obj-file saved to file. Typically a figure exported from Poser and modified with an external modeller (Blender etc). """ vertices = list() try: with open(filename, "r") as fh: for line in fh: if not line: break c, _, v = line.strip().partition(" ") if c == "v": vertices.append(map(float, v.split())) # Remove following line if vertices are not in one block, # so the whole file is processed. elif c in ("vt", "vn", "f"): break except IndexError: return ErrDialog("Vertex Error.", "Vertices in file '%filename' corrupted.") except IOError: return ErrDialog("File Error.", "File '{}' does not exist or is not accessible.". format(filename)) return NP.array(vertices, NP_PRECISION) def do_export(figure, onFinish=None): """ Export figure to Wavefront obj file. """ assert isinstance(figure, poser.FigureType) figurename = figure.Name() parms = collect_geometry(figure) vertices = parms["vertices"] geom = parms["geom"] use_material = CONFIG.get("CTRL_ExportTexture", True) use_groups = CONFIG.get("CTRL_ExportGroups", False) morphname = CONFIG["CTRL_MorphName"].strip() vertices *= int(CONFIG.get("Scale", 1)) if CONFIG.get("CTRL_SingleSelectFile", True): with wx.FileDialog(None, "Export Wavefront file", style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT | wx.FD_CHANGE_DIR, defaultDir=CONFIG.get("ExportPath", BASEPATH), defaultFile="{}-{}.obj".format(figurename, morphname) ) as dlg: if dlg.ShowModal() == wx.ID_CANCEL: return CONFIG["ExportPath"] = os.path.dirname(dlg.GetPath()) filename = dlg.GetFilename() else: filename = os.path.join(CONFIG["ExportPath"], "{}-{}.obj".format(figurename, morphname)) try: tmp = open(filename, "w") tmp.close() except IOError: ErrDialog("Can't create or write to file '{}'.", "Maybe you have to select another directory first.") return with open(filename, "w") as fh: print("### Date : %s" % time.asctime(), file=fh) print("### Figure : %s" % figurename, file=fh) print("### Vertices: %s" % len(vertices), file=fh) if use_material and geom.Materials(): matfile = filename.rsplit(".", 1)[0] + ".mtl" write_matfile(matfile, geom.Materials()) print("mtllib ./" + os.path.basename(matfile), file=fh) vertex_crosslist = NP.zeros(len(vertices), NP.int32) not_empty_idx = 0 for idx, vertex in enumerate(vertices): if vertex[0] != 0.0 and vertex[1] != 0.0 and vertex[2] != 0.0: print("v {} {} {}".format(*vertex), file=fh) vertex_crosslist[idx] = not_empty_idx not_empty_idx += 1 if use_material: for idx, tvert in enumerate(geom.TexVertices()): print("vt {} {}".format(tvert.U(), tvert.V()), file=fh) current_groups = list() current_mat = list() if not use_groups: print("g", figurename, file=fh) # experimental --- define smoothgroup print("s", figurename, file=fh) polys = geom.Polygons() tpolys = geom.TexPolygons() sets = geom.Sets() for idx in range(len(sets)): sets[idx] = vertex_crosslist[sets[idx]] tsets = geom.TexSets() for index, poly in enumerate(polys): if use_groups: if poly.Groups() != current_groups: current_groups = poly.Groups() print("g", ", ".join(current_groups), file=fh) # experimental --- define smoothgroup print("s", ", ".join(current_groups), file=fh) if use_material: if poly.MaterialName() != current_mat: current_mat = poly.MaterialName() print("usemtl", current_mat, file=fh) line = [str(sets[idx + poly.Start()] + 1) for idx in range(poly.NumVertices())] if use_material: tpoly = tpolys[index] for tidx, v in enumerate((tsets[idx + tpoly.Start()] + 1) for idx in range(tpoly.NumTexVertices())): line[tidx] += "/%d" % v print("f", " ".join(map(str, line)), file=fh) CONFIG["LastExported"] = filename import pickle with open(filename + ".cross", "wb") as fh: pickle.dump(vertex_crosslist, fh) if onFinish is not None: onFinish() return filename def do_import(figure, morphname): assert isinstance(figure, poser.FigureType) figurename = figure.Name() geom, actorlist, actor_indices = figure.UnimeshInfo() if CONFIG.get("CTRL_SingleSelectFile", True): old_filename = CONFIG.get("LastExported", None) if not old_filename: with wx.FileDialog(None, "Import Original exported Wavefront file", style=wx.FD_OPEN | wx.FD_CHANGE_DIR | wx.FD_FILE_MUST_EXIST, defaultDir=CONFIG.get("ImportPath", BASEPATH), defaultFile="{}-{}.obj".format( figurename, morphname) ) as dlg: if dlg.ShowModal() == wx.ID_CANCEL: return old_filename = dlg.GetFilename() with wx.FileDialog(None, "Import Wavefront file as morph", style=wx.FD_OPEN | wx.FD_CHANGE_DIR | wx.FD_FILE_MUST_EXIST, defaultDir=CONFIG.get("ImportPath", BASEPATH), defaultFile="{}-{}_mod.obj".format( figurename, morphname) ) as dlg: if dlg.ShowModal() == wx.ID_CANCEL: return CONFIG["ImportPath"] = os.path.dirname(dlg.GetPath()) new_filename = dlg.GetFilename() else: old_filename = os.path.join( CONFIG["ExportPath"], "{}-{}.obj".format(figurename, morphname)) new_filename = os.path.join( CONFIG["ImportPath"], "{}-{}_mod.obj".format(figurename, morphname)) verts_new = read_vertices(new_filename) verts_old = read_vertices(old_filename) if len(verts_old) != len(verts_new): ErrDialog("Vertices mismatch.", "Old number of vertices: {}." "New number of vertices: {}.". format(len(verts_old), len(verts_new))) return vertices = (verts_new - verts_old) / int(CONFIG.get("Scale", 1)) del verts_new del verts_old import pickle with open(old_filename + ".cross", "rb") as fh: verts_crosslist = pickle.load(fh) body = figure.ParentActor() masterdial = body.Parameter(morphname) if masterdial is None: body.CreateValueParameter(morphname) masterdial = body.Parameter(morphname) if masterdial is None: return ErrDialog("Morph Error.", "Can't find or create morph in body actor.") for actor_idx, actor in enumerate(actorlist): morph = list() for i, v_idx in enumerate(actor_indices[actor_idx]): # x, y, z = map(lambda a: round(a, PRECISION), vertices[v_idx]) x, y, z = map(lambda a: round(a, PRECISION), vertices[verts_crosslist[v_idx]]) if x != 0 or y != 0 or z != 0: morph.append((i, x, y, z)) if len(morph) == 0: continue morphparm = actor.Parameter(morphname) if morphparm is None: actor.SpawnTarget(morphname) morphparm = actor.Parameter(morphname) if morphparm is None: return ErrDialog("Morph Error", "Can't create Morphtarget.") if not morphparm.IsMorphTarget(): return ErrDialog("Morph error.", "Morph Parametername ('%s')\n" "already exist but is not a morph" % morphname) for i in range(actor.Geometry().NumVertices()): morphparm.SetMorphTargetDelta(i, 0, 0, 0) for i, x, y, z in morph: morphparm.SetMorphTargetDelta(i, x, y, z) while morphparm.NumValueOperations(): morphparm.DeleteValueOperation(0) morphparm.AddValueOperation(poser.kValueOpTypeCodeKEY, masterdial) vop = morphparm.ValueOperations()[0] vop.InsertKey(0, 0) vop.InsertKey(1, 1) masterdial.SetMinValue(-.5) masterdial.SetMaxValue(1.0) APP_NAME = "Figure Importer/Exporter" STD_COLOR = 120, 120, 120 LBL_COLOR = 80, 80, 80 BG_COLOR = 75, 75, 75 HL_COLOR = 100, 100, 150 FG_COLOR = 200, 200, 200 TX_COLOR = 0xfe, 0xfe, 0xfe STOPP_UPDATE_UI = False class GridBagManager(object): __slots__ = "parent", "sizer", "flag", "border", "current_row", "font" def __init__(self, *args, **kwargs): for varname in self.__slots__: setattr(self, varname, kwargs.get(varname, None)) for idx, entry in enumerate(args): if self.__slots__[idx] not in kwargs: setattr(self, self.__slots__[idx], entry) self.current_row = 0 assert isinstance(self.parent, wx.Panel) assert isinstance(self.sizer, wx.GridBagSizer) assert isinstance(self.flag, int) assert isinstance(self.border, int) def addrow(self, *args, **kwargs): row = int(kwargs.get("row", self.current_row)) col = int(kwargs.get("startcol", 0)) flag = kwargs.get("flag", self.flag) font = kwargs.pop("font", self.font) widgets = [] for idx, widget in enumerate(args): if font: widget.SetFont(font) self.sizer.Add(widget, pos=(row, col + idx), flag=flag, border=self.border) widgets.append(widget) self.current_row += 1 return widgets def setTooltip(ctrl, text): if text and ctrl: t = wx.ToolTip(text) t.SetAutoPop(5000) ctrl.SetToolTip(t) return ctrl def ColoredCtrl(ctrl, **kwargs): ctrl.SetBackgroundColour(kwargs.pop("bgcolor", BG_COLOR)) ctrl.SetForegroundColour(kwargs.pop("fgcolor", FG_COLOR)) return setTooltip(ctrl, kwargs.pop("tooltip", None)) def LabelCtrl(parent, **kwargs): bg_color = kwargs.pop("bgcolor", BG_COLOR) fg_color = kwargs.pop("fgcolor", FG_COLOR) font = kwargs.pop("font", SYS_FONT) tooltip = kwargs.pop("tooltip", None) ctrl = wx.StaticText(parent, **kwargs) ctrl.SetFont(font) ctrl.SetBackgroundColour(bg_color) ctrl.SetForegroundColour(fg_color) return setTooltip(ctrl, tooltip) def PrepCtrl(parent, ctrl, **kwargs): bind = kwargs.pop("bind", []) fgcolor = kwargs.pop("fgcolor", FG_COLOR) bgcolor = kwargs.pop("bgcolor", BG_COLOR) font = kwargs.pop("font", None) value = kwargs.pop("value", None) tooltip = kwargs.pop("tooltip", None) ctrl = ctrl(parent, **kwargs) if bind: if isinstance(bind[0], (tuple, list)): for bind_entry in bind: assert len(bind_entry) == 2 ctrl.Bind(bind_entry[0], bind_entry[1]) else: assert len(bind) == 2 ctrl.Bind(bind[0], bind[1]) ctrl.SetForegroundColour(fgcolor) ctrl.SetBackgroundColour(bgcolor) if font: ctrl.SetFont(font) if value: ctrl.SetValue(value) return setTooltip(ctrl, tooltip) class AppPanel(wx.Panel): _CONFIGCHANGED = False def __init__(self, parent, name="Fullbody Morphs", style=wx.DEFAULT, size=(270, 400), **kwargs): super(self.__class__, self).__init__(parent=parent, id=wx.ID_ANY, name=name, style=style, size=size, **kwargs) read_config() self.stdfont = SYS_FONT self.gb_manager = GridBagManager(parent=self, sizer=wx.GridBagSizer(0, 0), flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=2 ) self.figurelist = PrepCtrl(self, wx.Choice, choices=[], style=wx.CB_SORT | wx.NO_BORDER, size=(80, 20), name="figurelist", font=self.stdfont.SetPointSize(8), tooltip="Right click to reload Figurelist.", bind=((wx.EVT_RIGHT_UP, self.updateFigurelist), (wx.EVT_CHOICE, self.onChoice)) ) self.updateFigurelist() self.initUI(self.gb_manager) self.Bind(wx.EVT_WINDOW_DESTROY, self.onClose) # self.Bind(wx.EVT_MOUSE_EVENTS, lambda ev: ev.StopPropagation()) self.Bind(wx.EVT_SIZE, self.onSize) self.updateUI() self.Layout() def initUI(self, gbm): assert isinstance(gbm, GridBagManager) self.SetBackgroundColour(BG_COLOR) self.SetForegroundColour(FG_COLOR) self.SetFont(self.stdfont) btn_size = (80, 15) gbm.addrow(PrepCtrl(self, wx.Button, label="Export Figure", name="BTN_ExportFigure", style=wx.BORDER_NONE | wx.BU_EXACTFIT, size=(50, 30), bgcolor=STD_COLOR, fgcolor=(0xD0, 0xC0, 0x30), tooltip="Export currently selected figure.", bind=((wx.EVT_LEFT_UP, self.onExportModel), (wx.EVT_ENTER_WINDOW, self.onEnter_button), (wx.EVT_LEAVE_WINDOW, self.onLeave_button)) ), PrepCtrl(self, wx.Button, label="Import Morph", name="BTN_ImportMorph", style=wx.BORDER_NONE | wx.BU_EXACTFIT, size=(50, 30), bgcolor=STD_COLOR, fgcolor=(0xD0, 0xC0, 0x30), tooltip="Import modified figure as morph.", bind=((wx.EVT_LEFT_UP, self.onImportModel), (wx.EVT_ENTER_WINDOW, self.onEnter_button), (wx.EVT_LEAVE_WINDOW, self.onLeave_button)) )) gbm.addrow(LabelCtrl(self, label="Figure", fgcolor=STD_COLOR, name="LBL_FigureList"), self.figurelist) gbm.addrow(LabelCtrl(self, label="Morphname", fgcolor=STD_COLOR, bgcolor=BG_COLOR), ColoredCtrl(wx.TextCtrl(self, value=CONFIG.setdefault("CTRL_MorphName", "Morph"), name="CTRL_MorphName", style=wx.BORDER_SIMPLE), bgcolor=BG_COLOR, fgcolor=TX_COLOR)) gbm.addrow(LabelCtrl(self, label="Increment Morph\non each import", fgcolor=STD_COLOR, bgcolor=BG_COLOR), PrepCtrl(self, wx.CheckBox, value=CONFIG.setdefault("CTRL_RenumberMorph", False), name="CTRL_RenumberMorph", style=wx.NO_BORDER, bind=((wx.EVT_CHECKBOX, self.onCheckBox),))) gbm.addrow(PrepCtrl(self, wx.Button, label="Export Path", style=wx.BORDER_NONE | wx.BU_EXACTFIT, size=btn_size, bgcolor=STD_COLOR, fgcolor=FG_COLOR, tooltip="Path to export current figure to.", bind=((wx.EVT_LEFT_UP, self.onExportPath), (wx.EVT_ENTER_WINDOW, self.onEnter_button), (wx.EVT_LEAVE_WINDOW, self.onLeave_button)) ), PrepCtrl(self, wx.Button, label="Import Path", style=wx.BORDER_NONE | wx.BU_EXACTFIT, size=btn_size, bgcolor=STD_COLOR, fgcolor=FG_COLOR, tooltip="Path where exported figures are stored.", bind=((wx.EVT_LEFT_UP, self.onImportPath), (wx.EVT_ENTER_WINDOW, self.onEnter_button), (wx.EVT_LEAVE_WINDOW, self.onLeave_button)) )) gbm.addrow(LabelCtrl(self, label="Use Fileselection", fgcolor=STD_COLOR, bgcolor=BG_COLOR), PrepCtrl(self, wx.CheckBox, style=wx.NO_BORDER, value=CONFIG.setdefault("CTRL_SingleSelectFile", True), name="CTRL_SingleSelectFile", tooltip="Select file on each Import/Export", bind=((wx.EVT_CHECKBOX, self.onCheckBox),))) gbm.addrow(LabelCtrl(self, label="Export groups", fgcolor=STD_COLOR, bgcolor=BG_COLOR), PrepCtrl(self, wx.CheckBox, style=wx.NO_BORDER, value=CONFIG.setdefault("CTRL_ExportGroups", False), name="CTRL_ExportGroups", tooltip="Export actor groups", bind=((wx.EVT_CHECKBOX, self.onCheckBox),))) gbm.addrow(LabelCtrl(self, label="Export UV", fgcolor=STD_COLOR, bgcolor=BG_COLOR), PrepCtrl(self, wx.CheckBox, style=wx.NO_BORDER, value=CONFIG.setdefault("CTRL_ExportTexture", True), name="CTRL_ExportTexture", bind=((wx.EVT_CHECKBOX, self.onCheckBox),))) gbm.addrow(LabelCtrl(self, label="Move Texturefiles", fgcolor=STD_COLOR, bgcolor=BG_COLOR), PrepCtrl(self, wx.CheckBox, style=wx.NO_BORDER, value=CONFIG.setdefault("CTRL_MoveTextures", True), name="CTRL_MoveTextures", bind=((wx.EVT_CHECKBOX, self.onCheckBox),))) gbm.addrow(LabelCtrl(self, label="Scale", fgcolor=STD_COLOR, bgcolor=BG_COLOR), ColoredCtrl(wx.TextCtrl(self, name="CTRL_Scale", value=str(CONFIG.setdefault("Scale", 1)), style=wx.SIMPLE_BORDER | wx.TE_RIGHT), fgcolor=FG_COLOR, bgcolor=BG_COLOR)) gbm.addrow(LabelCtrl(self, label="Edit Light", fgcolor=STD_COLOR, bgcolor=BG_COLOR), PrepCtrl(self, wx.CheckBox, style=wx.NO_BORDER, value=False, name="CTRL_EditLight", bind=((wx.EVT_CHECKBOX, self.onEditLight),))) gbm.sizer.AddGrowableCol(0) gbm.sizer.AddGrowableCol(1) sz = wx.BoxSizer(wx.VERTICAL) sz.AddMany([ (gbm.sizer, 0, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, 10), ]) sz.SetSizeHints(self) self.SetSizer(sz) wx.CallAfter(self.updateUI) def onSize(self, ev): # CONFIG["Perspective"] = aui.SavePaneInfo(paneInfo) # self._CONFIGCHANGED = True ev.Skip() def updateUI(self): obj = self.FindWindowByName("LBL_FigureList") if obj: c = (0xff, 0, 0) if self.figurelist.GetCount() == 0 else STD_COLOR obj.SetForegroundColour(c) if self._CONFIGCHANGED: write_config() self._CONFIGCHANGED = False if not STOPP_UPDATE_UI: wx.CallLater(300, self.updateUI) def onChoice(self, ev): choice = ev.GetEventObject() if choice.GetName() == "figurelist": # type: wx.Choice idx = choice.GetCurrentSelection() if idx == -1: CONFIG["figure"] = "" else: CONFIG["figure"] = choice.GetString(idx) def onRadioBox(self, ev): try: obj = ev.GetEventObject() CONFIG[obj.GetName()] = obj.GetValue() except Exception: raise finally: ev.Skip() def onEditLight(self, ev): try: light = poser.Scene().Actor("Edit Light") except poser.error: pass else: light.SetLightOn(ev.GetEventObject().Value) poser.Scene().DrawAll() def onCheckBox(self, ev): try: obj = ev.GetEventObject() CONFIG[obj.GetName()] = obj.GetValue() except Exception: raise finally: ev.Skip() def onExportModel(self, ev): """:type ev: wx.Event""" def reset_color(): obj.SetBackgroundColour(STD_COLOR) obj.Update() try: idx = self.figurelist.GetCurrentSelection() if idx < 0: ErrDialog("No figure selected.") return sc = wx.FindWindowByName("CTRL_Scale") CONFIG["Scale"] = sc.GetValue() obj = wx.FindWindowByName("CTRL_MorphName") CONFIG["CTRL_MorphName"] = obj.GetValue() obj = ev.GetEventObject() obj.SetBackgroundColour((0xff, 0, 0)) obj.Update() figurename = self.figurelist.GetString(idx) figure = poser.Scene().Figure(figurename.strip()) do_export(figure, onFinish=None) obj.SetBackgroundColour(STD_COLOR) obj.Update() except Exception: raise finally: ev.Skip() def onImportModel(self, ev): try: sc = wx.FindWindowByName("CTRL_Scale") CONFIG["Scale"] = sc.GetValue() idx = self.figurelist.GetCurrentSelection() if idx < 0: ErrDialog("No figure selected.") return figurename = self.figurelist.GetString(idx) figure = poser.Scene().Figure(figurename.strip()) morph_ctrl = wx.FindWindowByName("CTRL_MorphName") morphname = morph_ctrl.GetValue().strip() if morph_ctrl else "MORPH" obj = ev.GetEventObject() obj.SetBackgroundColour((0xff, 0, 0)) obj.Update() do_import(figure, morphname) obj.SetBackgroundColour(STD_COLOR) check = wx.FindWindowByName("CTRL_RenumberMorph") if check and check.GetValue(): morphname, _, nr = morphname.partition(" ") morphname += " " + str(int(nr or 0) + 1) morph_ctrl.SetValue(morphname) except Exception: raise finally: ev.Skip() def onExportPath(self, ev): try: defaultpath = CONFIG.get("ExportPath", CONFIG.get("ImportPath", CONFIG.get("BASEPATH", BASEPATH))) with wx.DirDialog(self, "Choose Export Directory", defaultpath, style=wx.DD_DEFAULT_STYLE ) as dlg: if dlg.ShowModal() == wx.ID_OK: CONFIG["ExportPath"] = dlg.GetPath() self._CONFIGCHANGED = True except Exception: raise def onImportPath(self, ev): try: defaultpath = CONFIG.get("ImportPath", CONFIG.get("ExportPath", CONFIG.get("BASEPATH", BASEPATH))) with wx.DirDialog(None, "Choose Import Directory", defaultpath, style=wx.DD_DEFAULT_STYLE ) as dlg: if dlg.ShowModal() == wx.ID_OK: CONFIG["ImportPath"] = dlg.GetPath() except Exception: raise finally: ev.Skip() def onEnter_button(self, ev): obj = ev.GetEventObject() if obj.BackgroundColour == STD_COLOR: obj.SetBackgroundColour(HL_COLOR) ev.Skip() def onLeave_button(self, event): obj = event.GetEventObject() if obj.BackgroundColour == HL_COLOR: obj.SetBackgroundColour(STD_COLOR) event.Skip() def onClose(self, event): global STOPP_UPDATE_UI STOPP_UPDATE_UI = True CONFIG["Perspective"] = aui.SavePaneInfo(paneInfo) CONFIG["CTRL_MorphName"] = wx.FindWindowByName( "CTRL_MorphName").GetValue() CONFIG["Scale"] = wx.FindWindowByName("CTRL_Scale").GetValue() write_config() def updateFigurelist(self, *ev): if poser: while self.figurelist.GetCount(): self.figurelist.Delete(0) for idx, fig in enumerate(poser.Scene().Figures()): self.figurelist.Append(fig.Name()) if fig == poser.Scene().CurrentFigure(): self.figurelist.SetSelection(idx) if __name__ == "__main__": read_config() aui = poser.WxAuiManager() root = aui.GetManagedWindow() SYS_FONT = root.GetFont() paneInfo = aui.GetPane(APP_NAME) if paneInfo.IsOk(): aui.ClosePane(paneInfo) paneInfo = wx.aui.AuiPaneInfo() savedinfo = CONFIG.get("Perspective", None) if savedinfo is not None: aui.LoadPaneInfo(savedinfo, paneInfo) else: paneInfo.name = APP_NAME paneInfo.Resizable(True).FloatingSize( wx.Size(250, 280)).BestSize(wx.Size(200, 230)) paneInfo.Movable(True).DestroyOnClose(True) paneInfo.Name(APP_NAME).Caption(" PoMo Bridge +++ 0.98a ") MainPanel = AppPanel(parent=root, name=APP_NAME) aui.AddPane(MainPanel, paneInfo) paneInfo.Show() aui.Update()