''' Wrappers and helper classes to work with Softimage. ''' from win32com.client import constants as const import win32com STR_CODEC = 'utf-8' xsi = win32com.client.Dispatch('XSI.Application') xsiui = win32com.client.Dispatch('XSI.UIToolkit') xsimath = win32com.client.Dispatch('XSI.Math') class SoftimageError(Exception): def __init__(self, value): self.value = value def __repr__(self): return 'SofimageError: {0}'.format(self.value) class Softimage(object): @staticmethod def get_objects(name): xsifact = win32com.client.Dispatch('XSI.Factory') collection = xsifact.CreateObject('XSI.Collection') collection.items = name if collection.Count > 0: return list(collection) return () @staticmethod def get_object(name): try: return xsi.Dictionary.GetObject(name) except win32com.client.pythoncom.com_error: print 'COM ERROR' return None @staticmethod def get_plugin_origin(plugin_name): xsi = win32com.client.Dispatch('XSI.Application') plugins = xsi.Plugins for plugin in plugins: if plugin.Name == plugin_name: return plugin.OriginPath[:-20] @staticmethod def msg(message, msg_type=const.siMsgOkOnly, caption='Information'): return xsiui.MsgBox(message, msg_type, caption) @classmethod def get_all_children(cls, root): '''Recursively adds children to a list.''' children = [] children.append(root) if root.Children(0): chldrn = list(root.Children) for child in chldrn: children.extend(cls.get_all_children(child)) return children @staticmethod def get_playcontrol(): return xsi.Dictionary.GetObject('PlayControl') class SIScene(object): def get_playcontrol(self): return xsi.Dictionary.GetObject('PlayControl') def get_name(self): return xsi.ActiveProject.ActiveScene.Name def wirecol(self, r, g, b): wr = int(round(r * 7)) << 1 wg = int(round(g * 7)) << 4 wb = int(round(b * 7)) << 7 return wr + wg + wb class SIModel(object): def __init__(self, si_model): self.si_model = si_model self.geo = si_model.ActivePrimitive.GetGeometry2(0) def get_geo(self, model): if model: return model.ActivePrimitive.GetGeometry2(0) else: return self.si_model.ActivePrimitive.GetGeometry2(0) def get_uv_props(self): cls = self.si_model.ActivePrimitive.GetGeometry2(0).Clusters sample = cls.Filter('sample') for cls in sample: props = cls.Properties.Filter('uvspace') if props.Count >= 1: return props def get_normal_props(self): clusters = self.geo.Clusters.Filter('sample') for cluster in clusters: normal_clusters = cluster.Properties.Filter('normal') if normal_clusters.Count >= 1: return normal_clusters def set_normals(self, index, normals): prop = self.get_normal_props()[index] prop.Elements.Array = normals def get_envelope_props(self): pnt_clusters = self.geo.Clusters.Filter('pnt') for cluster in pnt_clusters: properties = cluster.Properties weight_props = properties.Filter('envweights') if weight_props.Count >= 1: return weight_props def get_vertex_color_props(self): cls = self.si_model.ActivePrimitive.GetGeometry2(0).Clusters sample = cls.Filter('sample') for cls in sample: props = cls.Properties.Filter('vertexcolor') if props.Count >= 1: return props def set_weights(self, index, weights): prop = self.get_envelope_props()[index] prop.Elements.Array = weights return True def set_uvs(self, index, uvs): prop = self.get_uv_props()[index] prop.Elements.Array = uvs return True def set_vertex_colors(self, index, colors): prop = self.get_vertex_color_props()[index] prop.Elements.Array = colors return True def get_vis(self, model): vis = model.Properties.Filter('visibility') prop = vis[0] val = prop.viewvis.Value if val: return True return False def get_transform_quat(self, model): transform = model.Kinematics.Local.Transform quat = xsimath.CreateQuaternion() transform.GetRotationQuaternion(quat) sca = transform.SclX, transform.SclY, transform.SclZ rot = quat.X, quat.Y, quat.Z, quat.W tra = transform.PosX, transform.PosY, transform.PosZ return tra, rot, sca def is_uved(self): sample_clusters = self.geo.Clusters.Filter('sample') for cls in sample_clusters: props = cls.Properties uv_props = props.Filter('uvspace') if uv_props.Count > 0: return True def is_colored(self): sample_clusters = self.geo.Clusters.Filter('sample') for cls in sample_clusters: props = cls.Properties vcol_props = props.Filter('vertexcolor') if vcol_props.Count > 0: return True def is_weighted(self): pnt_clusters = self.geo.Clusters.Filter('pnt') for cluster in pnt_clusters: properties = cluster.Properties weight_props = properties.Filter('envweights') if weight_props.Count > 0: return True class SIMaterial(object): def get_clip_source_name(self, clip): src = clip.Source filename = src.Parameters('FileName').Value filename_list = filename.split('\\') return filename_list[-1].encode(STR_CODEC) def get_shader_color(self, shader, color): col = shader.Parameters(color).Value return col.Red, col.Green, col.Blue, col.Alpha class SIGeneral(object): @staticmethod def get_plugin_origin(plugin_name): xsi = win32com.client.Dispatch('XSI.Application') plugins = xsi.Plugins for plugin in plugins: if plugin.Name == plugin_name: return plugin.OriginPath[:-20] def get_objects_by_name(self, modelnames): models = [] for name in modelnames: xsifact = win32com.client.Dispatch('XSI.Factory') collection = xsifact.CreateObject('XSI.Collection') collection.items = name models.append(collection(0)) return models def msg(self, message, msg_type=const.siMsgOkOnly, plugin='XSIZETools'): return xsiui.MsgBox(message, msg_type, plugin) def get_obj_by_name(self, name): xsifact = win32com.client.Dispatch('XSI.Factory') collection = xsifact.CreateObject('XSI.Collection') collection.items = name if collection.count == 1: return collection(0) def check_existence(self, name): xsifact = win32com.client.Dispatch('XSI.Factory') collection = xsifact.CreateObject('XSI.Collection') collection.items = name return collection.Count def get_main_material_name(self, obj): if obj.Material: return obj.Material.Name return 'Scene_Material' def get_all_children(self, root): if root: return self._get_all_children(root) else: return None def _get_all_children(self, root): '''Recursively adds children to a list.''' children = [] children.append(root) if root.Children(0): chldrn = list(root.Children) for child in chldrn: children.extend(self.get_all_children(child)) return children def unique_materials(self, obj_list): materials = self.all_materials(obj_list) unique = [] unique_names = [] for mat in materials: if mat.Name not in unique_names: unique.append(mat) unique_names.append(mat.Name) return unique def all_materials(self, obj_list): materials = [] for obj in obj_list: # Non-polymsh objects sometimes dont have a # material, so just ignore them. if obj.Type != 'polymsh': continue geo = obj.ActivePrimitive.GetGeometry2(0) if obj.Material: materials.append(obj.Material) else: materials.append('Scene_Material') for cls in geo.Clusters: if cls.Material: materials.append(cls.Material) return materials def material_name_dict(self): dict_ = {} lib = self.xsi.ActiveProject.ActiveScene.MaterialLibraries[0] for mat in lib.Items: dict_[mat.Name] = mat return dict_ class SIProgressBar(object): def __init__(self): self.bar = xsiui.ProgressBar def show(self): self.bar.Visible = True def hide(self): self.bar.Visible = False def set(self, maximum, capt, val=0, step=1): self.bar.Value = val if maximum: self.bar.Maximum = maximum else: self.bar.Maximum = 1 self.bar.Caption = capt self.bar.Step = step def setc(self, capt): self.bar.Caption = capt def inc(self): self.bar.Increment()