【Maya】 キーボードを使用したプログラムの制御 【plugin】
2016/12/27
皆さんお久しぶりです。開発室の望月です。
気づいたら冬がきました。寒いです。
さて、今回はキーボード等のデバイスを用いたプログラムの制御について御紹介できればと思います。
Maya,Photoshop,zbrush..etcのDCC系のツールを使ったことのある方はわかると思うんですが、
Ctrlキーを押しながら操作すると別のツールになるとか、Shiftキーを押すと別のブラシになるとか、そう。あれです。
地味な話ですが、ツールによっては物理デバイスでの制御はユーザーエクスペリエンス(以下UX)を高める上で非常に重要な要素になります。
今回の記事ではWindows環境のMayaのコマンドプラグインをベースにして話を進めます。
始めに
実行環境は以下の物になります。
- Windows 7 x64
- Visual Studio 2012 VC-11
- Maya 2016
- python(maya付属)
今回はwindowsのAPIを使用します。Linux、Mac環境だと実装が変わります。唯プログラムの流れ自体は変わらないので基本を押さえてれば移植は容易だと思います。
コマンドプラグイン
最低限のコードを掲載します。
今回はプラグインに関してはあまり掘り下げません。こちらのコードで重要なのはwindows.hファイル、doIt()関数とcommnadName変数で、
他はmayaに登録するために必要なコードであり、今回は重要ではありません。
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 | #include <maya/MFnPlugin.h> #include <maya/MStatus.h> #include <maya/MPxCommand.h> #include <maya/MGlobal.h> #include <Windows.h> //こいつが主役です。 #include <string> const std::string vendor( "DigitalFrontier.inc" ); const std::string version( "feature" ); const std::string apiVersion( "2016" ); const std::string commandName( "for_dfTalk" ); //mayaで呼び出すときのコマンド名 namespace dftalk{ class customCommand : public MPxCommand{ public : customCommand(){}; virtual MStatus doIt( const MArgList& argList ){ //要チェックや return MStatus::kSuccess; }; static void * creator(){ return new customCommand(); }; }; } // -- Initialize process MStatus initializePlugin( MObject obj ) { MFnPlugin plugin( obj, vendor.data(), version.data(), apiVersion.data() ); CHECK_MSTATUS_AND_RETURN_IT( //マクロです。失敗するとMStatus::kFailureをreturnします。 plugin.registerCommand( commandName.data(), dftalk::customCommand::creator ) ); return MStatus::kSuccess; } // -- unInitialize process MStatus uninitializePlugin( MObject obj ) { MFnPlugin plugin( obj ); CHECK_MSTATUS_AND_RETURN_IT( plugin.deregisterCommand( commandName.data() ) ); return MStatus::kSuccess; } |
こちらのコードをvisual studio等を使用してビルドしてください。
詳しい手順は弊社斎藤の記事を参照してください。
はじめてC++で書くMayaプラグイン
キーボードでの制御コードの追加
それでは、今回の記事の目玉である部分の実装に入ります。
先ほどのコードの下記の部分に実装を追加します。
1 2 3 | virtual MStatus doIt( const MArgList& argList ){ return MStatus::kSuccess; }; |
コードを次のように書き換えます。
1 2 3 4 5 6 7 8 9 10 11 12 | virtual MStatus doIt( const MArgList& argList ){ if ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ){ MGlobal::displayInfo( "control pushed!!!" ); } else if ( GetAsyncKeyState( 'A' ) & 0x8000 ){ MGlobal::displayInfo( "A pushed!!!" ); } else { MGlobal::displayInfo( "none!!!" ); } return MStatus::kSuccess; }; |
実装の説明をすると、ctrlキーが押されている状態でコマンドが実行されれば “control pushed!!!” と出力、Aキーが押されていれば “A pushed!!!” と出力、それ以外は “none!!!” と出力します。
つまり GetAsyncKeyState() 関数がキーボードの状態を取得できる関数という事になります。
引数として渡せるキーコードは、下記リンク先をご覧ください。
microsoftキーコード一覧
「リンクなぞ飛ばん!!」という硬派な方のために。
ツールの実装に良く使う修飾キーを下記に置いときます。
キー | コード | 16進数 |
---|---|---|
SHIFT | VK_SHIFT | 0x10 |
CTRL | VK_CONTROL | 0x11 |
ALT | VK_MENU | 0x12 |
Mayaで使ってみよう
それではMaya上でテストしてみましょう。
上記のdoIt()関数に書き換えた後ビルドしたプラグインファイルをロードして。スクリプトエディター上でこちらのpythonスクリプトを実行してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import maya.cmds as cmd name = 'dfTalk' if cmds.window( name,exists = True ): cmds.deleteUI( win ) win = cmds.window( name ) cmds.columnLayout( adj = True ) title = "push" cmds.button( title,command = "cmds.for_dfTalk()" ) #こちらでカスタムコマンドの登録 cmds.showWindow() |
ウィンドウが出て来たと思います。次にCtrlキー、Aキーを押してボタンをクリックしてみましょう。成功していれば、このようになるはずです。
Python上での実装について
ここまではC++での実装を行ってきました。次はPython上で制御したいと思います。
先ほどのpythonのコードを下記のように書き換えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import maya.cmds as cmd from ctypes import * name = 'dfTalk' if cmds.window( name,exists = True ): cmds.deleteUI( win ) win = cmds.window( name ) cmds.columnLayout( adj = True ) title = "push" if windll.user32.GetKeyState( 0x11 ) & 0x8000 : title = "control on !!" cmds.button( title,command = "cmds.for_dfTalk()" ) cmds.showWindow() |
上記コードを実行するときに、Ctrlキーが押されていればボタンのタイトルを書き換える処理が実行されます。
おわりに
駆け足でしたが、プログラムに対してキーボードで処理を制御する方法を、御紹介いたしました。これで隠しコマンドを入れることができますね。
今回はwindowsのAPIを使用したものになりましたが、Qt、Pyside等を使うことでLinux、Mac等を考慮したポータブルな実装にできるかもしれません。※未検証
例としてキーボードを取り上げましたが、他のデバイスでも十分に使える技術ですので、御活用して頂けたら幸いです。
※免責事項※
本記事内で公開している全ての手法・コードの有用性、安全性について、当方は一切の保証を与えるものではありません。
これらのコードを使用したことによって引き起こる直接的、間接的な損害に対し、当方は一切責任を負うものではありません。
自己責任でご使用ください。
コメント
コメントフォーム