一半君的总结纸

听话只听一半君

#15 应该如何命名界面控件( UI controls)? 用自己起的名字还是 Maya 自动赋予的名字,哪种方法好?

在本站大多数MEL范例中,你会发现我通常让Maya自动给一个control赋予名字,并把这个名字储存在一个字符串变量里(这个名字通常是该control的完整路径).

string $button = `button`;
// Result: window1|columnLayout18|button1 //

button -e -label "Push Me" $button;

当然Maya也允许你在创建control的时候指定一个自己的名字 .

button myButton;
// Result: window1|columnLayout18|myButton //

button -e -label "Push Me" myButton;

那为什么我们不任何时候都自己起名字呢? 这两种方法各有优缺点. 用哪种方法取决于你的script里后面如何用这个control.

为了让例子更简短,我通常在创建control的时候用Maya自动赋予的名字,并把他存在字符串变量里. 我觉得这样可以减少错误发生的几率,并且让例子的思路更清晰,读者比较容易看懂.

在大多数“真实世界”中的实际使用中的scripts,我都会使用自己起的名字,原因是我总是需要在main proc函数的外面访问这些UI controls,如果我不自己起独特的名字,只要一个proc需要访问UI,那我就得把UI controls的名字作为参数传给他,如果每个proc都要这样做会很麻烦.

如果你决定用自己起的名字,那你就必须确保使用的名字是独一无二的. 如果你起了一个之前已经用过的名字,那 Maya 就会认为这个名字表示的是最近一次指向的UI,之前指向的UI就没办法访问了(其实依然可以,只不过要通过完整路径访问). 比如.

string $window = `window`;
  columnLayout;
    button myButton;
showWindow $window;

// Result: window1|columnLayout18|myButton //

现在还没事. 但是看看如果你把上面的script再运行一次会发生什么?

// Result: window2|columnLayout19|myButton //

好了现在有两个窗口,每个窗口里都有一个label是”myButton”的button,假如你想改button的label:

button -e -label "Push Me" myButton;

你会发现第二个窗口 ‘window2’的button的label变成了”Push Me”. 但如果你其实只是想改‘window1’窗口里的button呢? 那你必须首先知道这个control的完整路径 — ‘window1|columnLayout2|myButton’ — 这个路径是在创建这个control的时候知道的,因为你可以把他创建时候的返回值保存起来.(如果你是在新开的Maya里运行上面的script两次,那上面才应该是columnLayout2,如果你已经开了很多其他窗口,那就可能不是了,不过你可以用#101的方法得到这个完整路径)

所以当你自己给control起名字的时候,你得:

  1. 确保你的UI在任何时候只有一个实例(instance). 这很容易做到; 我的每个script里都会像下面这么写.
    // 如果 window 已经存在,那就先删掉他
    if ( `window -exists «windowName»` )
      deleteUI -window «windowName»;
    
    // 现在创建一个新的 window
    window «windowName»;
    
  2. 为了避免和其他script(包括Maya自带的,你从网上下的,或者你自己写的)的UI命名冲突, 给你所有的control名字前面都加个前缀(prefix). 比如我自己写的H2O scripts 的control名字都是以”h2o_”开头的. 我甚至还加上了表示这个control是哪个script里面的前缀,比如在我的H2O’s Game Editor script里我的所有controls都是以 “h2o_ge_”开头的.

但有些时候,使用Maya自动赋予的名字更好,甚至是必须使用自动的名字.

我在写UI的时候经常用formLayout. 大部分时候我用formLayout 的时候,在设置attachment flags时我总是用自动赋予的control名,而不是又长又难记的自己起的名字,把controls的名字存到字符串变量里再用比直接用要容易的多了.

string $form = `formLayout`;

// add controls here //

formLayout -e
// −attachForm, et al //
  $form;

通常我尽量把 scripts写的模块化(modularization),这样很多functions就可以在其他地方被重复使用了. 这样做带来的结果是通常同样名字的control可能被创建了很多次,这违背了我上面提到的第一条命名control要独一无二的原则. 所以这种情形下,你必须使用在创建control时Maya自动赋予的名字.

比如, 你想给任意窗口的menuBar加一个菜单( menu).(你这个加菜单的function是个通用的,可以被很多script调用) 显然这个创建菜单的function必须接受一些参数,告诉他要给哪个窗口加菜单,以及这个菜单被选中的时候运行什么命令之类的. 这个方法在 Scene Management Menu (此连接已挂,也许以后找到会加上)里有举例.

global proc makeWindowWithMenu()
{
  // 创建一个带 menuBar 的 window
  string $window = `window -menuBar true`;

  // 给这个 window 加一个 menu
  addMyMenu( $window );

  showWindow;
}

global proc addMyMenu( string $window )
{
  // 确认这个 window 有 menuBar
  if ( `window -q -menuBar $window` )
  {
    // 把当前的 parent 设为此 window
    setParent $window;

    // 添加 menu
    string $theMenu = `menu -label "The Menu"`;

      // 创建一个 menuItem
      // 这个 menu 的 command 里含有上面的 `menu` 命令的返回值,(来表明要加到哪个menu上)
      menuItem -label "Add item to this menu" -c ( "addAnotherMenuItem( \"" + $theMenu + "\" )" );

      setParent ..;
  }
}

proc addAnotherMenuItem( string $menu )
{
  // 设置将要新创建的 menuitem 的parent 为 menu
  setParent -m $menu;

  // 添加一个新的 menuItem
  menuItem -label "Another Item";
}

也许你想创建一组controls,并把他们”dock”到已有windows的layout里,同时希望这一组control可以有多个实例(instance). 一个实际中的例子是 rolloInt(链接已挂). Maya自己的 ‘scriptedPanel’ 可以做到类似的效果,原理也相同.

大多数时候, 你如何命名你的controls并不是太要紧,无论是自己起名还是让Maya自动起,重要的是你的script的内容决定了哪种方法比较适合,唯一需要注意的是不要让多个controls拥有同样的名字.

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: