_581x100.png CGsyomei_583x102.gif 訪問者 無料カウンター ページビュー 無料カウンター

2009年10月10日

Maxscript勉強中その4 ちょっとめんどくさいTree Stormの名前関連。

 Maxscript _study4.jpg

今やっている仕事でTree Stormを使って木を大量に作っているんですが、困ったことにTree Stormで作った木は「Acer Platanoides 3y01」みたいに名前にスペースができるので、スクリプトでどうこうしようとする時にエラーを多発して結構困ってます。なので、とりあえずオブジェクトの名前のスペースを見つけてそれをアンダーバーに置き換えるスクリプトを考えてみました。

---------------------------------------------------------------------------------------------------------

carSelect = filterString $.name " " --carSelectに、選択したオブジェクトの名前から" "でくくられたスペース部分をフィルタリングした文字列を配列を代入。例えば#("Acer", "Platanoides", "3y01")みたいな感じに。



carNum = carSelect.count--文字列の中の文字数をカウント。それを変数carNumに代入。



spaceNum = carNum as integer -1 --先ほど取得した全文字数から1引いた数がスペースの数。それを変数spaceNumに代入。


for i = 1 to spaceNum do --1から取得したスペースの数の回数分リネームを実行。

(
$.name = replace $.name (findString $.name " ") 1 "_"

)

---------------------------------------------------------------------------------------------------------
 考えたといっても殆ど人に聞きまくりな現状なんですが^^;とりあえずよく訳が分からないことがいろいろあって、例えばcarNum = carSelect.countの部分で文字をカウントしたけど(ここでは3が帰って来ました。)、それを次にいちいちspaceNum = carNum as integerと整数化しないとエラーを出すんですね。ちゃんと「3」と数字が出ているけど、この状態だと文字として認識されているということなのか分かりません。

 あとforループでスペースの個数分文字の置き換えの式を回せばいいというところまでは思いついたけど、じゃあiを式のどこにぶち込めばいいんだ?みたいな疑問に突き当たっちゃいました。でも別にiをどうこうしなくてもforループ回るんですね。まだこんな初歩的なところで躓いてます^^;




 あとちょっとスクリプトが長くなったので前半をすっきりまとめたら

---------------------------------------------------------------------------------------------------------

for i = 1 to (((filterString $.name " " ).count) as integer -1) do

(
$.name = replace $.name (findString $.name " ") 1 "_"

)

---------------------------------------------------------------------------------------------------------


こうできたんですが、これはさすがに分かりづらいw多分まだシンプルな方なんでしょうけど。

あとwhileループでやる方法はこんな感じで。これならいちいちスペースの数を数えなくていいんでこっちの方がスマートですね。findStringが該当する文字を見つけられない時にundefinedを返してくるのを利用してwhileループを脱出するきっかけにしていると。これは自分じゃまだ思いつかないです。

---------------------------------------------------------------------------------------------------------

(
a = true
while a == true do
(

ind = findString $.name " "--処理したい文字が何文字目なのか?indは数字、もしくは該当する文字がない場合はundefinedが帰ってくる。
if ind != undefined then $.name = replace $.name ind 1 "_"--undefinedを返してくるまで$.name = replace $.name ind 1 "_"をループし続ける。undefinedが帰ってくるときは処理すべき文字(スペース)がもうない場合。
else a = false  --ループが終わるとfalesを返してwhileループ終了。
)
)

---------------------------------------------------------------------------------------------------------


 また、名前にスペースがあるオブジェクトはいろいろエラーを出すと言いましたが、例えばselect $Box 01みたいなのはだめだけど、オブジェクト名をシングルクゥオーテーションで囲めばOkなんですね。select $'Box 01'ここら辺のお約束事大体分かってきました。

 今後の課題としては、今は単一のオブジェクトに対してのリネームですが、スペースを含むオブジェクトだけを自動選択して複数オブジェクトに対して同じ事をするというのをやりたいです。しかしまあ現状どうにもどうやればいいか思いつきません。ここを突破できればいろいろ楽しくなりそうなんですが・・・。まだまだ先は長そうです。
posted by けゑ at 06:02| Comment(4) | TrackBack(0) | Max Script
この記事へのコメント
いつも興味深い内容でちょくちょく拝見していますー。初投稿です。
自分もスクリプトを始めてもがいているので、少しでも助けになればと。
複数オブジェクトに一気に適用したいならこんなのどうでしょう?

for i in selection do
(
if findString i.name " " == undefined then
(
)
else
(
i.name = replace i.name (findString i.name " ") 1 "_"
)
)

単純にスペースないオブジェクトはundefined返すので、それ以外に適用させる感じです。
Posted by mat●uno at 2009年10月12日 16:49
さきほどのやつだと複数のスペースあった場合は対応できないので、けゑさんが前記したwhile文を入れたほうがいいですね。

for i in selection do
(
a = true
while a == true do
(
if findString i.name " " != undefined then
(
i.name = replace i.name (findString i.name " ") 1 "_"
)
else
(
a = false
)
)
)

何度もすいません..。
Posted by mat●uno at 2009年10月12日 17:46

function replaceText var=
(
sel = getCurrentSelection()
for obj in sel do
(
if var == 1 do
(
textArray = filterString obj.name " ";
newObjName = "";
for i=1 to textArray.count do
(
if (i+1)>textArray.count then
(
newObjName += textArray[i];
)
else
(
newObjName += textArray[i] + "_" ;
)
)
print "Variation 1"
print newObjName;
--obj.name = newObjName;
)
if var == 2 do
(
--Only Available in Max2008 and Higher
newObjName = substituteString obj.name " " "_";
print "Variation 2"
print newObjName;
--obj.name = newObjName;
)

)
)

replaceText 1;


2008からもっと簡単なFunctionが用意されてありますよ。
substituteString <source_string> <from_string> <to_string>
↑コイツです。
MAYAでのテキスト絡みの時、よく使われますけど、MAXにも全く同じ名前のFunctionがあるんですね、素敵です :)

バリエーション1は2008以前のバージョン用です。

そして、Maxでバージョン情報を取得して、その情報でバリエーション1か2か自動的に適用できますが、
会社にMAX2010しかないので、参照できる他のバージョン情報も無いので、諦めました…Orz

この辺はご自由にカスタマイズしてくださいね ;)

MAXの配列は1からスタートなんですね…マジで迷惑です...

*実際使用する時には、--obj.name前の”--”を外して、そのまま使えます。
Posted by まだまだNewbie at 2009年10月13日 14:49
>mat●unoさん どうもー。いろいろ手直しありがとうございます。もうmat●unoさんスクリプト極めてるじゃないですか。さすがです。2番目のやつはかなり汎用性高くていいですね。これなら木が何千本あっても問題なさそうです。これこそスクリプトの醍醐味ですね。  いやー、ほんとまだあんまり構文とか覚え切れてないことが多くて全然まともに使えてません。特にfor文の中にwhile文とか入ってくるとちょっと混乱してきますね。このかっこはどのかっこだったっけみたいな。慣れたらなんてことないんでしょうけどね。まだ一から書こうとするとどうしてもエラーがでてしまうというか。もうちょっとスクリプト脳になるまで頑張ってみますよ。 >まだまだNewbieさん 度々ありがとうございます。substituteString <source_string> <from_string> <to_string>よさそうですね。ちょっと忙しくてきちんとまだ試してないんですが、あとで復習してみます。MAXのバージョン取得でプログラムの適応の分岐を作るのは勉強になります。まだ全然慣れてなくてif文forループ構文などが複雑に混在するとどう追っていけばいいのか分からなくなってしまうので、これを機にこういった複雑なスクリプトに慣れていきたいです。  配列の0からのスタートは初心者には逆にかなり分かりづらいんですが、まあ他のメジャーな言語に慣れた人にはかなり混乱を招きそうですね^^;ほんとここら辺は統一して欲しいものですが。
Posted by けゑ at 2009年10月14日 13:16
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/32805108

この記事へのトラックバック