原理

  通过选择的顶点生成面片,根据面片挤压出盒子。
  原理并不复杂,之前做的面片自动匹配插件也有很多相同的地方

  但是鉴于连续顶点选择的时候,会有序号相连的情况,为此我特意开发了一个函数来处理这个问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
global proc FXTD_seperatePtNum(string $sel[]){
string $str = "";
string $PtStr[] = {};//清空数组
for($j = 0; $j < size($sel); $j++ ){

//查看数组是否包含 : 信息
$str = `match ":" $sel[$j]`;

if($str == ""){//没有就是正常的点
$PtStr[size($PtStr)] = $sel[$j];
}else{

string $buffer2[];
string $buffer3[];
string $buffer4[];

//分离出 [***:***] 当中的数字 例如[123:321]
tokenize `match "[0-9]+]" $sel[$j]` "]" $buffer2;
tokenize `match "vtx[[0-9]+:" $sel[$j]` "[" $buffer3;

//获取面的名字
tokenize $sel[$j] ".vtx" $buffer4;


//数据类型转换
int $temp_1 = $buffer3[1];
int $temp_2 = $buffer2[0];

//添加到数组最后的位置
for($i = 0; $i + $temp_1 <= $temp_2; $i++ ){

$PtStr[size($PtStr)] = ($buffer4[0] + ".vtx[" + ($i + $temp_1) + "]");
}

}

$str = "";

}

$sel = $PtStr;
}

//获取选择的顶点
$sel = `ls -sl`;

//清楚相连的序号重新存储到数组中
FXTD_seperatePtNum($sel);

float $vtx_position[] = {};//清空数组

//将收集的点的位置信息批量放进数组中
for($j = 0; $j < size($sel); $j++ )
{
FXTD_floatPush($vtx_position,`xform -q -ws -t $sel[$j]`);
}

//根据选择的点生成多边形
string $temp_tri[] = `polyCreateFacet -ch off -tx 1 -s 1
-p $vtx_position[0] $vtx_position[1] $vtx_position[2]
-p $vtx_position[3] $vtx_position[4] $vtx_position[5]
-p $vtx_position[6] $vtx_position[7] $vtx_position[8]`;

2019-10-26 补充
其实ls -fl可以通过 flattern 参数将这种数组展平(:з」∠)

序号错乱问题

  目前这种方案可以解决选点问题,直接生成模型。
  然而序号是从小到大排序而非选择的顺序。
  这会导致面片错乱的情况。

操作截图

  为了解决这个问题,就需要记录选点的顺序操作。
  然而网上找不到相关的资料(MEL真的是太小众了)
  于是只好自己去想办法
  而我所想到唯一靠谱的方案就是使用scriptjob动态记录选择。
  因为理论上每一个选择都需要存储到数组中,从而实现顺序记录。
  然而这种方案写起来很痛苦的

  终于,最后费了我九牛二虎之力才在CGsociety中找到了2005年的解决方案。
  当然原先的解决方案可能年代久远吧,有点问题,我进行了一些修改。
  原答案是针对选择边提出的解决方案,其实迁移到其他地方并不困难。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
global string $selectOrder_edges[];
global string $selectOrder_updateSet;
global int $selectOrder_jobNum;

global proc string[] selectOrder ()
{
// Get globals
global string $selectOrder_edges[];
global string $selectOrder_updateSet;
global int $selectOrder_jobNum;

if ( !`scriptJob -exists $selectOrder_jobNum` || $selectOrder_jobNum == 0 ) {//判断scriptJob 是否已经开启了

//题头信息提示用户
headsUpMessage "开始监听-选择内容";

//清空数组
$selectOrder_edges = {};

//创建选择集 记录当前的选择
string $selEdges[] = `ls -sl`;
$selectOrder_updateSet = `sets -n selectOrderSet $selEdges`;

//添加scriptJob 记录信息
$selectOrder_jobNum = `scriptJob -event SelectionChanged "selectOrder.update"`;

} else {//如果scriptJob 已经开启了

headsUpMessage "停止监听-选择内容";

//删除选择集
delete $selectOrder_updateSet;

//注销scriptJob
scriptJob -kill $selectOrder_jobNum -force;
}

//返回记录选择的数组
return $selectOrder_edges;
}

//scriptJob 动态记录函数
global proc selectOrder.update ()
{
// Get Globals
global string $selectOrder_edges[];
global string $selectOrder_updateSet;

// Get change
string $selEdges[] = `ls -sl`;

//创建选择集 将当前的选择放进去
string $tempSet = `sets -n selectOrderSetTemp $selEdges`;

//减去之前已经选择的部分
string $diff[] = `sets -sub $tempSet $selectOrder_updateSet`;

//添加-fl flatten 标签可以 清理序号相连的问题
$diff = `ls -fl $diff`;

//将选择集放入到string数组中
$selectOrder_edges = stringArrayCatenate($selectOrder_edges,$diff);

//删除选择集
delete $tempSet;
delete $selectOrder_updateSet;

//重新创建选择集
$selectOrder_updateSet = `sets -n selectOrderSet $selEdges`;
}

  这里使用了-fl标签,通过内置flag,完美解决了我上面头疼的序号问题。(:з」∠)
  这个方法我测试了一下,确实可以记录操作顺序,但是也有其他的问题。
  开启了scriptJob之后撤销就会很麻烦。
  每一次都要按一下来开启scriptjob

  想到ls 还有-fl 这样的操作,我就想官方会不会已经提供了什么解决方案。
  于是我又在官方文档中寻找。
  还真的找到了更为简洁的解决方案。

1
2
3
4
5
6
//开启 记录选择顺序
selectPref -trackSelectionOrder 1;

//-fl flattern清理序号相连问题
//-os orderSelected 按顺序获取选择
$sel = `ls -fl -os`;

  如此开发中所有的坑都已经解决了,剩下的只是界面和挤压面片的操作而已。

总结

  MEL真的不好弄,不像JavaScript,资料一大堆。
  CG行业现在普遍都用python进行开发了,MEL小众语言被挤得没有生存空间。
  但是开发Maya插件始终是离不开MEL的,即便使用pymel,代码的源头还是来自于MEL。