2014-10-31 55 views
0

我正在使用Autodesk Maya程序。 我已经制定了一个命名约定脚本,它将相应地为某个约定中的每个项目命名。不过,我每次都在场景中列出它,然后检查所选名称是否与场景中的任何当前名称相匹配,然后重命名它并在场景中重新检查一次,如果有重复。在很长的时间内对一个大的unicode列表进行迭代?

但是,当我运行代码时,可能需要长达30秒到一分钟或更长时间才能完成所有操作。起初,我不知道是什么让我的代码运行缓慢,因为它在相对较低的场景中运行良好。但是,当我将打印语句放在检查场景代码中时,我发现检查场景中的所有项目需要很长时间,并检查重复项。

ls()命令提供场景中所有项目的unicode列表。如果场景中的物品数量适中,这些物品可能会相对较大,达到一千或更多,正常情景会比我目前的测试场景大几倍(其中有大约794个物品在此列表中)。

这应该需要这么长时间吗?我用来比较效率低下的方法吗?我不确定这里要做什么,代码需要花费过多的时间,我也想知道它是否可以是代码中的其他任何东西,但这看起来可能就是这样。

以下是一些代码。

class Name(object): 
    """A naming convention class that runs passed arguments through user 
    dictionary, and returns formatted string of users input naming convention. 
    """ 

    def __init__(self, user_conv): 
     self.user_conv = user_conv 
     # an example of a user convention is '${prefix}_${name}_${side}_${objtype}' 

    @staticmethod 
    def abbrev_lib(word): 
     # a dictionary of abbreviated words is here, takes in a string 
     # and returns an abbreviated string, if not found return given string 


    @staticmethod 
    def check_scene(name): 
     """Checks entire scene for same name. If duplicate exists, 

     Keyword Arguments: 
     name -- (string) name of object to be checked 
     """ 

     scene = ls() 
     match = [x for x in scene if isinstance(x, collections.Iterable) 
         and (name in x)] 
     if not match: 
      return name 
     else: 
      return '' 

    def convert(self, prefix, name, side, objtype): 
     """Converts given information about object into user specified convention. 

     Keyword Arguments: 
     prefix -- what is prefixed before the name 
     name -- name of the object or node 
     side -- what side the object is on, example 'left' or 'right' 
     obj_type -- the type of the object, example 'joint' or 'multiplyDivide' 
     """ 
     prefix = self.abbrev_lib(prefix) 
     name = self.abbrev_lib(name) 
     side = ''.join([self.abbrev_lib(x) for x in side]) 
     objtype = self.abbrev_lib(objtype) 
     i = 02 
     checked = '' 
     subs = {'prefix': prefix, 'name': name, 'side': 
      side, 'objtype': objtype} 
     while self.checked == '': 
      newname = Template (self.user_conv.lower()) 
      newname = newname.safe_substitute(**subs) 
      newname = newname.strip('_') 
      newname = newname.replace('__', '_') 
     checked = self.check_scene(newname) 
     if checked == '' and i < 100: 
      subs['objtype'] = '%s%s' %(objtype, i) 
      i+=1 
     else: 
      break 
    return checked 
+0

你有没有做过任何分析,找出时间正在采取? – jonrsharpe 2014-10-31 19:28:07

+0

不知道该怎么做,仍然是一种新的python和使用IDE。 – 2014-10-31 19:33:49

+0

https://docs.python.org/2/library/profile.html – jonrsharpe 2014-10-31 19:42:02

回答

1

你运行这么多次? while self.checked ==''内的每次迭代都有可能拖延几百或几千项清单,这可能是一个罪魁祸首。在Maya中,FWIW打印速度也非常慢,特别是如果您打印一份长长的清单 - 无论如何做这么多次,一定会很慢。同时

  1. 限制你搜索到一个类型 - 为什么巨魔通过数百个任意的节点,如果你只关心MultiplyDivide现在:

    我想尝试一些事情,以加快这个吗?

  2. 使用集合或字典进行搜索,而不是使用哈希表集合和字典进行搜索,并且查找速度更快
  3. 如果您担心保持命名传递,绝对要将其设计为抵制Maya的默认设置行为,即追加数字后缀以保持名称的独特性。任何不支持这一点的命名约定都将是一段时间的痛处,因为你无法阻止Maya在正常的业务过程中这样做。另一方面,如果您将它用于不同的实例,则根本不需要执行任何分析 - 只需在对象上使用rename()并捕获结果即可。 Maya不会重新命名为全球唯一性,只有本地化 - 因此,如果您想为不是兄弟姐妹的事物创建独特的节点名称,则必须自己完成。

这里是寻找唯一的节点名称一些便宜货代码:

def get_unique_scene_names (*nodeTypes): 
    if not nodeTypes: 
     nodeTypes = ('transform',) 
    results = {} 
    for longname in cmds.ls(type = nodeTypes, l=True): 
     shortname = longname.rpartition("|")[-1] 
     if not shortname in results: 
      results[shortname] = set() 
     results[shortname].add(longname)  
    return results 

def add_unique_name(item, node_dict): 
    shortname = item.rpartition("|")[-1] 
    if shortname in node_dict: 
     node_dict[shortname].add(item) 
    else: 
     node_dict[shortname] = set([item]) 

def remove_unique_name(item, node_dict): 
    shortname = item.rpartition("|")[-1] 
    existing = node_dict.get(shortname, []) 
    if item in existing: 
     existing.remove(item) 


def apply_convention(node, new_name, node_dict): 
    if not new_name in node_dict: 
     renamed_item = cmds.ls(cmds.rename(node, new_name), l=True)[0] 
     remove_unique_name(node, node_dict) 
     add_unique_name (renamed_item, node_dict) 
     return renamed_item 
    else: 
     for n in range(99999): 
      possible_name = new_name + str(n + 1) 
      if not possible_name in node_dict: 
       renamed_item = cmds.ls(cmds.rename(node, possible_name), l=True)[0] 
       add_unique_name(renamed_item, node_dict) 
       return renamed_item 
     raise RuntimeError, "Too many duplicate names" 

要使用它,在一个特定的节点类型,您只需提供调用apply_convention()当右想成为名。这会将场景中的所有关节(天真!)重命名为'jnt_X',同时保持后缀的唯一性。你会做一些更聪明,像你原来的代码一样 - 这只是确保在叶子是唯一的:

joint_names= get_unique_scene_names('joint')    

existing = cmds.ls(type='joint', l = True) 
existing .sort() 
existing .reverse() 
# do this to make sure it works from leaves backwards! 

for item in existing : 
    apply_convention(item, 'jnt_', joint_names) 

# check the uniqueness constraint by looking for how many items share a short name in the dict: 
for d in joint_names: 
    print d, len (joint_names[d]) 

但是,就像我说的,对于那些该死的数字后缀计划,玛雅使得他们所有的时间没有要求权限,所以你不能与战斗:(

+0

我发送字符串,然后它发出一个字符串名称,然后我使用rename()重命名一个新创建的对象。所以这不是什么问题。至于节点,它可能是一个不同的节点,可以说我有一个加减平均节点名称'average_pma',但由于某种原因,一个不同的节点被命名为'average_pma'。我想说明这一点,特别是考虑到我不只是命名曲线,而是组,定位器,实用程序节点,甚至着色器。 – 2014-11-01 03:04:19

+0

您可以通过添加多种类型,使原始集合尽可能复杂,但代价是性能较差 – theodox 2014-11-01 03:11:50

+0

但是,我认为速度更重要,因此我将切换脚本以解决此问题。我只会尝试使用给定的对象类型。 – 2014-11-01 03:14:41

0

而不是运行ls为每个name,你应该运行一次,商店,导致成set(无序列表 - 稍快一些)。然后检查,当你运行check_scene

def check_scene(self, name): 
    """Checks entire scene for same name. If duplicate exists, 

    Keyword Arguments: 
    name -- (string) name of object to be checked 
    """ 

    if not hasattr(self, 'scene'): 
     self.scene = set(ls()) 

    if name not in self.scene: 
     return name 
    else: 
     return '' 
相关问题