【覚書】maya python入門 其の四
肝心なことを書き忘れていたので、書いていきたいと思います。
色々書いてもあれなので、まずはコードを書いてみたいと思います。
import maya.cmds as cmds oCube = cmds.polyCube(w=1,h=1,n="Cube_Make") cmds.polyCube(oCube[0],e=True,sx=1,sy=2,sz=3) oSx = cmds.polyCube(oCube[0],q=True,sx=True) oSy = cmds.polyCube(oCube[0],q=True,sy=True) oSz = cmds.polyCube(oCube[0],q=True,sz=True) print oSx print oSy print oSz
立方体を作成して、サブディビジョンの値をを変えて、それをログに出しているだけです。
これで言わないといけない部分が
cmds.polyCube(oCube[0],e=True,sx=1,sy=2,sz=3)
この文の「e=True」という部分です。
前回は「getAttr」「setAttr」を使用して値を取得していましたが
MAYAは基本フラグを使用して
値を編集、取得できます。
それが上記文に書いている「e=True」これは「edit=True」の略語です。
文字通り「edit」なので、編集ができます。
参照(取得)は「q=True」「query=True」
上記スクリプトでいう
oSx = cmds.polyCube(oCube[0],q=True,sx=True) oSy = cmds.polyCube(oCube[0],q=True,sy=True) oSz = cmds.polyCube(oCube[0],q=True,sz=True)
の部分です。
queryの後にサブディビジョンの値を参照(取得)してます。
※サブディビジョンの値一気に取得できる方法ないのかな…
こんな感じでHELPをみて「E」「Q」マークがある物については
フラグの指定で値を編集、参照できたりします。
逆にその指定が無いフラグ、且つ取得編集ができるものについては
「getAttr」「setAttr」を使用して値をいじるわけですね。
あと、これもハマる部分なんですが、MAYAPythonって少数点の扱いがキチンとされていたりしますね。
なので、これで計算すると、四捨五入されてしまいます。
oNumber = 100/15 print oNumber
きちんと指定するとこんな感じ。
ただ、小数点を記載しただけです。
oNumber = 100.0/15.0 print oNumber
地味にハマる所ですよね。
こんな感じでフラグによる参照、編集のお話でした。
とこのまま終わると説明だけですげぇつまんない感じになりそうなので
一個だけ簡単なスクリプトを。
まずはコード。
import maya.cmds as cmds cmds.window(title="Anather_Window",widthHeight=(720, 480)) cmds.paneLayout() cmds.modelPanel() cmds.showWindow()
SIでいう、オブジェクトビュー的な感じを作成するものです。
アニメーションする時によく使うので(SIで)。。
ただ、これHELPに載っていた内容なので、探ればまだまだ色々できそうです。
以上です。
【覚書】maya python入門 其の三
では続き。
前回はSET側のコードで移動させたり、KEYを打ったりしてました。
今回はGET側をやってます。
まず初めに前回の環境を作成します。
import maya.cmds as cmds cmds.polyCube( n='Cube_Move' ) cmds.move( 5, 1, 1 ) cmds.setKeyframe( at='translateX',v=10 ,time=30 )
これで画像みたいな環境ができたと思います。
ここから値を取得して、編集してみたいと思います。
始めに移動値の値を取得します。
値を取るには「getAttr」を使用するみたいです。
※これ以外にもあるのかな??
import maya.cmds as cmds maya.cmds.select('Cube_Move') tx = maya.cmds.getAttr('.tx') print tx
これで取得できました。
getAttr('.tx') この部分の引数を変えてあげると色々取得できますね。
引数についてはこちらを
http://me.autodesk.jp/wam/maya/docs/Maya2009/CommandsPython/getAttr.html
ちなみに「tx」はトランスXです。
もちろん「translateX」と書くことも可能です。
他にも
「ty」「tz」トランスY、トランスZ
「rx」「ry」「rz」ロットXYZ
「sx」「sy」「sz」スケールXYZ
と書きます。
全体を取得したい時は
「translate」「rotation」「scale」と記述して下さい。
それぞれ「X,Y,Z」として取得できます。
では続いてはキーフレームを取得します。
ここについてはやり方が少し分からなかった(他にももっとあると思います)
ので、HELPで引っ掛かった「findKeyframe」を使用してみます。
import maya.cmds as cmds maya.cmds.select('Cube_Move') tx = cmds.findKeyframe( 'Cube_Move',timeSlider=True, which='first' )
※画像は値が「which='next'」となってますが「which='first'」の間違いです。。。
とりあえずこれで取得できました。
findKeyframeについてはこちらを参照。
findKeyframe command
これ以外だとこんな感じ?
import maya.cmds as cmds maya.cmds.select('Cube_Move') tx = cmds.keyframe('Cube_Move.translateX',index=(0,0),query=True); print tx
※結果は上の画像と全く同じです。
ただこれだと一番初めのキーしか取得できない。
一応逆に最後だけ調節すには、こんな感じで記述します。
import maya.cmds as cmds maya.cmds.select('Cube_Move') tx = cmds.keyframe( query=True, lsl=True, timeChange=True )
もしくはこんな感じ。
import maya.cmds as cmds last = cmds.findKeyframe(timeSlider=True, which='last') print lastKey
※結果は上の画像と全く同じです。
GetKeyinfo的なものは「findKeyframe」が一番近いですね。
これを使っていきます。
これで取得できました。
次に値の変更をしてみます。
今上の画像をみると「30Fと66F」にキーフレームがあります。
これを30Fを0Fに、66Fを70Fにした後に、その値を「0」にしてみましょう。
考察すると、頭のキーフレームとお尻のキーフレームが取れれば
なんとかなりそうですね。
って事でコード。
まずは先頭のキーを「0F」にしてみます。
import maya.cmds as cmds maya.cmds.select('Cube_Move') tx = cmds.keyframe(index=(0,0),timeChange=0)
これで先頭は変わりました。
続いてお尻のキーを移動、値変更してみます。
ラストキーフレームはどうやって取得したらいいのか?
全くわからなかったんで、indexで無理やり取得してみました。
値はtimeChange同様にChangevalueで変更できそうです。
import maya.cmds as cmds maya.cmds.select('Cube_Move') cmds.keyframe('Cube_Move',index=(0,0),timeChange=0) cmds.keyframe('Cube_Move',index=(1,1), timeChange=70, valueChange=0 )
うーん。。
すごく最終フレームの処理が汚いですね。
indexがあるんだからlastはあってよ…と思いますが。。
他にもTIMEで指定する方法もあったりしますが
どちらにしても汚いっすね。
import maya.cmds as cmds maya.cmds.select('Cube_Move') cmds.keyframe('Cube_Move',index=(0,0),timeChange=0) cmds.keyframe('Cube_Move',t=(66,66), timeChange=70, valueChange=0 )
※結果は上の画像と全く同じです。
こんな感じで「とりあえず」キーの取得ができました。
ここから拡張するとなると、折角値を取れたんで
キーを全体的にずらす方法を書いてみようと思います。
import maya.cmds as cmds def Time_Offset(): Offset_Number = cmds.textField( "Time_Offset", q=True, tx=True ) selected_object = cmds.ls( type=['animCurveTL','animCurveTU','animCurveTA','animCurveTT']) cmds.keyframe(selected_object,edit=True,relative=True,timeChange=Offset_Number) cmds.window(title="offset") cmds.columnLayout() cmds.textField( "Time_Offset" ) cmds.button( l="Offset", command="Time_Offset()" ) cmds.setParent( '..' ) cmds.showWindow()
こんなかんじで選択した物を、入力された値全体的にずらします。
内容は関数とか使ってますが、めちゃくちゃ簡単です。
def Time_Offset(): Offset_Number = cmds.textField( "Time_Offset", q=True, tx=True ) selected_object = cmds.ls( type=['animCurveTL','animCurveTU','animCurveTA','animCurveTT']) cmds.keyframe(selected_object,edit=True,relative=True,timeChange=Offset_Number)
関数部分です。
一行目で関数宣言し、二行目でインプットボックスを作成
三行目で選択した物をフィルタリング。
この時アニメーションしてるものだけに篩をかけております。
四行目はさっきのコマンドに、入力された値をいれているだけです。
cmds.window(title="offset") cmds.columnLayout() cmds.textField( "Time_Offset" ) cmds.button( l="Offset", command="Time_Offset()" ) cmds.setParent( '..' ) cmds.showWindow()
この部分はウィンドウ生成部分ですね。
詳しくは省きますが、WEBに腐るほど資料がありますよ…
PySide含めて…
…っと
長くなったので、今回はこの辺りで。
次回はアニメーションされたキーフレームのコピペをベースに行きたいと思います。
以上です。
【覚書】maya python入門 其の二
続いて値の設定について書いていきたいと思います。
SIと同じで、アトリビュートのGET,SETValueがあるみたいなんですが
値の設定だけならもっと簡単にできそうです。
今回はまず、SET側からみていきましょう。
import maya.cmds as cmds cmds.polyCube( n='Cube_Move' ) cmds.move( 5, 1, 1 )
とてもシンプルな内容ですね。
立方体を作成して、移動しているだけです。
ただこれSIと少し違ってトランスフォームについて書くわけではなく
「move」と大きく括って書くんですね。
※もちろんトランスフォーム指定して、移動させることも可能です。
とてもシンプルに思いました。
ではここからカスタムしていきたいと思います。
初めに移動したので、キーを打ってみたいと思います。
コードはこんな感じ。
import maya.cmds as cmds cmds.polyCube( n='Cube_Move' ) cmds.move( 5, 1, 1 ) cmds.setKeyframe()
すごくシンプルにキーが打てます。
setKeyframe()
これがキーを打つコマンドになります。
ただ、正直個人的には、パラメータ全体にキーが打たれますよね。
これだと、Fカーブエディタ(グラフエディタ)が汚くなります。
個人的に超絶これが嫌いなので、このままだと使うきすらありません笑
私みたいに、「必要なパラメータだけ打ちたい!」
こんな時はフラグを色々触るといいです。
setKeyframe コマンド
結構ありますね。。
個人的に、見ていって「レイヤー指定」ができるのは少し楽しみかも。
では、今回は移動のXパラメータを指定してみましょう。
こんな感じ。
import maya.cmds as cmds cmds.polyCube( n='Cube_Move' ) cmds.move( 5, 1, 1 ) cmds.setKeyframe( at='translateX' )
はい。
「setKeyframe( at='translateX' )」
ここでアトリビュートをトランスXに指定しているわけです。
とても簡単。
ちなみに、時間や値もsetKeyframe側で変更できますね。
import maya.cmds as cmds cmds.polyCube( n='Cube_Move' ) cmds.move( 5, 1, 1 ) cmds.setKeyframe( at='translateX',v=10 ,time=30 )
こんな感じで値をセットできます。
では次はSETでは無く、GETしてみたいと思います。
以上。
【覚書】maya python入門
一から説明用にmayaMelではなく、mayaPythonの資料を書く必要があったので
メモに残して行こうかと思います。
まずはSIでも同じだが、色々なサイトをめぐりました。
SIからの移行に関しても色々書いて頂いているダイキンさんのサイト
http://www.comtec.daikin.co.jp/DC/UsersNotes/index.html
MELで大変お世話になったサイト
http://www.not-enough.org/abe/manual/maya-python/introduction-python.html
上記のサイトは非常に分かりやすいので
それに沿って、簡易なものを一個一個実行して覚えていくスタイルにしてみます。
あ、あとは英語ですがデジタルチューターズもいい感じですね。
さて前置きはこの程度にしておいて
さっそくコード書いていきます。
今回Python自体の説明については省ける所は
ガンガン省いていきます。
※時間が無いので…
ではまずは選択からですね。
これが無いと始まりませんネ。
import maya.cmds as cmds cmds.select() oSel = cmds.ls(sl=True) print oSel
非常に簡単なコードです。
選択した物をリストにして、プリントしているだけですね。
SI的な感覚だと
import maya.cmds as cmds oSel = cmds.select() print oSel(0)
とかでできねぇのかよ!!!
とか思うんですが、MAYAさんは一度リストで取得する必要があるみたいです。
「oSel = cmds.ls(sl=True)」
ここですね。「ls」リストに「sl」選択を格納
としないとダメなんですね…
ちなみに
「Select」の引数については公式にやたらと羅列されておりますね。
http://help.autodesk.com/cloudhelp/2016/JPN/Maya-Tech-Docs/CommandsPython/select.html
ダイキンさんのサイトでも紹介してましたが、階層以下ノード全て(トランス、シェイプ含む)
選択するにはこんな感じにすればいいみたいです。
import maya.cmds as cmds cmds.select(hierarchy=True) oSel = cmds.ls(sl=True) print oSel
Selectの引数に「Hierarchy」(階層)の引数をONにするだけですね。
これは便利ですね。
ただこれだと全て選ばれるので、微妙に不便です。
なので、引数のところに色々条件を加えてみました。
トランスフォームノードだけ
import maya.cmds as cmds cmds.select(cmds.ls(selection=True, dagObjects=True, type='transform')) oSel = cmds.ls(sl=True) print oSel
シェイプノードだけ
import maya.cmds as cmds
cmds.select(cmds.ls(selection=True, dagObjects=True, type='shape'))
oSel = cmds.ls(sl=True)
print oSel
単純にSelectの引数にDagフラグを立て、タイプを絞っただけです。
こんな形でSIのフィルタや、Typeに近い感じで選択の取得ができます。
ふぅ。。
第一回目はとりあえずここまで。
次は特に考えてないので、お題が出れば作成してみたいと思います。
以上です。
AEメモ
簡単な事なんですが「あ、なるほど」と思ったのでメモに。
動画みたいにキラキラをアニメの素材っぽくランダムにする方法です。
1.まずは、画像みたいにシェイプレイヤーでキラキラ素材を作成し配置します。
作り方はヘルプ通りです。
今回はスターの5角形-7角形までを用意します。
※コンポは200*200(30fps)
2.プリコンして、黒背景を置きます。
3.黒背景に「Particular」を割り当てます。
4.設定を画像にみたいに設定します。
※画像では「0」になってますが、LIFEは「0.02」ですね。
5.続けてグロー感を出したいので、「StarGlow」を割り当て画像のパラメータに設定します。
6.またコマ抜きしたいので、「ポスタリゼーション時間」も割り当てます。
2コマ抜きでなので、パラメータは「15」にしてます。
これで完了です。
続けて、この動画
これも正直上のやり方とほぼ一緒です。一応説明。
1.500*500(30fps)でコンポ作成し新規レイヤーを作成後、マスクで雷っぽい感じでマスクを抜いていきます。
2.それを複数個作成し、画像みたい配置していきます。
3.プリコンして、平面を作成しこれに「Particular」をアサイン
4.パラメーターは画像を参照
※ポイントは「Velocity」と、「Size over Life」です。
5.こちらも同様にグローとポスタリゼーション時間をアサインします。
これで完了。
とまぁこんな感じで、「Particular」でアニメっぽいやり方の紹介でした。
以上。
簡単動画管理ツールについて
以前作っていた、動画をまとめるスクリプトを色々カスタムしてみました。
というにも、資料の管理が煩雑になってきたので、自宅NASにサーバーとして
管理したいなぁーと思っていたので作りました。
仕事では、引き出し用に使ってたりします。
本当は「WhiteBrowser」とか使いたいんですが、あれインストールがいるんで
正直手を広げにくいです。
なのでブラウザベースで「簡単」「軽い」「分かり易い」を
元にざっくりなものとなります。
用意するのは画像みたいな階層です。
フォルダ名はなんでもOKです。
こんな感じで今回は軽めで用意してみました。
中身はこんな感じ。
数は少なめ。
私が持っている素材【MOV】が圧倒的に多いので、ブラウザ表示に関しては
Movと少しだけ対応しております。
もちろん追加も可能です。後述致します。
んで、まずは動画をコンバートツールにドロップします。
ちなみにコンバートツールの中身はこんな感じ。
ではドロップ。
すると、こんなウィンドウで止まると思います。
文字化けしてますが、今回はスルーで。
特に問題ありません。
これでOK押していただくとOKです。
※FFMEPGについてはググる等でお調べ頂くと
本当に得しますので、おすすめです。
この状態で以下の画像みたいに「.Gif」画像ができていると思います。
これがブラウザで表示する本体になります。
※このGIF化はFFMEPGが対応する全てのフォーマットでコンバート可能となります。
であとは、下記に記載するスクリプト【Make_HTML.wsf】を実行して下さい。
こんな感じになるかと思います。
入力する名前は、【フォルダ名】にして下さい。
ここに記載されたフォルダを見て、HTMLファイルを作る感じになります。
色々入ってますが、今はスルーで。
実行完了すると画像みたいに、フォルダ名のHTMLファイルが出来ていると思います。
でそれをブラウザで確認すると以下のHTMLファイルが立ち上げると思います。
はい。これでほぼ完了です。
あとはTOP画像とか、任意の画像をHTMLファイルにテキストで書き込んであげると完成です。
一応TOP画像はこんな感じにしてます。
※超簡単な感じです。
HTMLは詳しくないのでこんな感じしかできませんでした。
色々フリーのツール使うといいかもですね。
要はサムネイルが欲しかっただけんです笑
なんで作ってみました。
現状だと数は少ないので見た目がスカスカですが
お見せできない資料なども含めると30Pぐらい埋まってます笑
これがiPhoneで見れると一番いいですけどね…
ってことでコード
FFMEPGコンバートツールについては、以前の記事を参考下さい。
ココtommy-on.hatenablog.com
ではコード↓↓↓
<job id="foo"> <script language="VBScript"> 'InputBoxを出して、ユーザから入力された値を返す関数 function vbinput(msg) vbinput = InputBox(msg,"makehtml") end function </script> <script language="JavaScript"> //上で定義した関数を呼び出す var name = vbinput("書き出すIDを記入して下さい"); var objShell = new ActiveXObject("Shell.Application"); var fs = WScript.CreateObject("Scripting.FileSystemObject"); var targetPath = "D:\\動画まとめサイト\\"+name; var enuItems = new Enumerator (objShell.Namespace(objShell.Namespace(targetPath)).Items()); var Array_hako = new Array(); var file = fs.CreateTextFile(targetPath+"\\"+name+".html",true); for (; !enuItems.atEnd(); enuItems.moveNext()) { var item = enuItems.item(); var ntime = item.ExtendedProperty("Duration"); var time_math = ntime / 10000000; var frame = time_math * 30; var time_number = new Number(frame); var time = Math.round(time_number); var type = item.ExtendedProperty("Type"); if(type == "QuickTime ムービー" || type == "ビデオ クリップ" || type == "AVI ファイル") { //WScript.Echo( item.Name ); var Item_Name = item.name; var Out = Item_Name.lastIndexOf("."); var Final_Name = Item_Name.slice(0,Out); Array_hako.push(Final_Name); Array_hako.push(time+"フレーム"); //file.WriteLine( item.Name ); //file.WriteLine( time+"フレーム" ); } } //Array_hako.sort(); //WScript.Echo( Array_hako ); //ここからHTML作成 file.WriteLine( '<?xml version="1.0" encoding="Shift_JIS"?>' ); file.WriteLine( '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' ); file.WriteLine( '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">' ); file.WriteLine( '<head>' ); file.WriteLine( ' <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">' ); file.WriteLine( ' <title>'+name+'</title>' ); file.WriteLine( ' <link rel="stylesheet" type="text/css" href="../layout.css" />' ); file.WriteLine( ' <style type="text/css">' ); file.WriteLine( ' div.imagebox {' ); file.WriteLine( ' border: solid 2px #000000;' ); file.WriteLine( ' background-color: #eeeeff;' ); file.WriteLine( ' width: 350px;' ); file.WriteLine( ' float: left;' ); file.WriteLine( ' margin: 5px;' ); file.WriteLine( ' }' ); file.WriteLine( ' p.image, p.caption {' ); file.WriteLine( ' text-align: center;' ); file.WriteLine( ' margin: 5px;' ); file.WriteLine( ' }' ); file.WriteLine( ' p.caption {' ); file.WriteLine( ' border: solid 1px #000000;' ); file.WriteLine( ' font-size: 80%;' ); file.WriteLine( ' color: darkblue;' ); file.WriteLine( ' }' ); file.WriteLine( ' p.exp {' ); file.WriteLine( ' clear: left;' ); file.WriteLine( ' }' ); file.WriteLine( ' </style>' ); file.WriteLine( '</head>' ); file.WriteLine( '<body>' ); file.WriteLine( ' <!-- ヘッダ -->' ); file.WriteLine( ' <div id="footer"><h1><a href="../top.htm">'+name+' Topへ</a></h1>' ); file.WriteLine( ' </div>' ); for(var i=0; i<Array_hako.length; i++) { //WScript.Echo( Array_hako[i] ); file.WriteLine( ' <div class="imagebox">' ); file.WriteLine( ' <p class="image"><img src="'+Array_hako[i]+'.gif" alt="'+Array_hako[i]+'" ></p>' ); file.WriteLine( ' <p class="caption">'+Array_hako[i]+'</p>' ); file.WriteLine( ' <p class="caption">フレーム数:'+Array_hako[i+1]+'</p>' ); file.WriteLine( ' </div>' ); i = i + 1; } file.WriteLine( '</body>' ); file.WriteLine( '</html>' ); file.Close(); fs = null; objShell = null; </script> </job>
色々なサイトを参考にさせて頂きました。
ありがたやありがたや…
で、最後に上記で記載していたMov、AVI以外の対応ですが、
スクリプト38行目の
「 if(type == "QuickTime ムービー" || type == "ビデオ クリップ")」
この部分に動画ファイルの形式を【||】で追加していって下さい。
とりあえずAVIを足すなら、こんな感じです。
「 if(type == "QuickTime ムービー" || type == "ビデオ クリップ" || type == "AVI ファイル")」
これてAVIがHTMLに追加されると思います。
今後はこれをベースにPythonでもっと高機能な物を
作っていきたいですね。
以上です。
Pythonコピペツール
テストも兼ねて軽いものですが、テキスト読み込むツールを作成しました。
最近本格的にPython触るのんですが、約1年ぶりに触ったためか
殆ど忘れてて焦ってます…
ではまずはコード
とりあえず、「pyscripter」で動作確認済みです。
# -*- coding: utf-8 -*- #------------------------------------------------------------------------------- # Name: fileCheck.py # Purpose: スクリプトを配置したフォルダでテキストを参照して # 記載がないものを消したり、表示したりするプラグイン # 使い方は上記に書いている通り、テキストと比較したいフォルダに # このスクリプトを配置して、比較対象のテキストも「list_base.txt」として # 配置して下さい。あとは実行するだけです。 # 操作する場合は最終行を色々カスタム下さい。 # Author: tommy_on # #------------------------------------------------------------------------------- import os # osモジュールのインポート import re # 正規表現モジュールのインポート # os.listdir('パス')配列にファイルを格納 files = os.listdir(os.path.dirname(__file__)) pick = []#空の配列を用意 obj_del = [] f = open('list_base.txt','r')#検索するファイル一覧があるテキストを開き、配列で取得 for k in f.readlines(): pick.append(k)#速度保持の為、一度配列に格納 f.close() a_str = map(str,pick)#なんとなく文字列の方がサーチが早いような気がしたので文字列化 del_joint = ",".join(a_str)#カンマで区切り入れて for file in files: basename, extension = os.path.splitext(file)#スピリットして、拡張子を取得 if extension == ".txt" or extension == ".csv":#一応テキストとCSVを指定。※何となく。 Find_name = re.search (file, del_joint)#pickでは使われていないファイルを取得 if Find_name is None: os.remove(file) #input_f = input("パイソンはこれでインプット使えるみたい。")
こんな感じにします。消したいファイルがあるフォルダにスクリプトと比較用のテキストを配置します。
テキストは比較毎に改行しておいて下さい。
不要なデータを削除する時に使いますが、今回はすごく限られた状態のツールになります。
んで、あとは実行するだけ。
すると、画像みたいに、テキストになかったファイルが消えます。
現状ファイルの関係で「list」ファイルも削除しております。
これに問題が出た際はLISTテキストに自身のテキストファイルを描き込んでおくと
消されません。
最後コメントアウトしている部分は、先日知ったコードなので
忘れない内にここに書いておこうと思いますw
要は「インプットボックス」を表示するだけのものなんですが
知らなくて、いつもPySideでやってたんで…
以上です。