マニピュレータは、ヘルパー オブジェクトのタイプで、3D ビューポートでのパラメータの直接操作をサポートするように設計されています。マニピュレータを設定して、オブジェクト、モディファイヤ、コントローラ、ノードのパラメータを操作できます。
メイン ツールバーに[マニピュレータ](Manipulate)ボタンがあります。これを押すとシステムは、選択したオブジェクトのマニピュレータをすべて表示します。マニピュレータはマウスが通過するときに赤くなり、ツールチップ ポップアップ リストには、マニピュレータにより影響を受けるパラメータの現在の値の名前が表示されます。値を操作するには、左マウス ボタンでギズモをクリックしてから、ドラッグします。大半のマニピュレータは、できるだけギズモが現在のマウス位置の下を通るように設計されています。
マニピュレータには 2 つの種類があります。1 つは、「操作」モードに入るときに自動的に作成されるマニピュレータです。ホットスポット マニピュレータがこれに相当します。もう 1 つの種類はスタンドアロン オブジェクトで、スライダ マニピュレータがこれに相当します。これらは通常、使い勝手を向上させるために、パラメータ ワイヤリングとともに使用されます。
スタンドアロン マニピュレータを作成するには、[作成](create)パネルの「ヘルパー」に移動して、ドロップダウン リストの「マニピュレータ」を選択します。
操作するためにスタンドアロン マニピュレータを選択する必要はありません。ただし、ホットスポット マニピュレータのように自動的に作成されるマニピュレータは、選択したオブジェクトに対してのみ表示されます。
マニピュレータは、3D ギズモと 2D(画面スペース)ギズモの両方をサポートします。3D ギズモの例としてホットスポット マニピュレータを、2D ギズモの例としてスライダを挙げることができます。
マニピュレータは、標準の MAX プラグインとして C++ で作成するか、MAXScript に実装することができます。MAXScript では、これらはスクリプト プラグイン オブジェクトの 1 つのタイプです。このため、独自のマニピュレータを記述する場合は、まず最初に「スクリプト プラグイン」を読むことをお勧めします。これは、スクリプトで記述されたジオメトリ オブジェクトと非常によく似ています。
サンプル コードとして使用可能な 3 つのスクリプト マニピュレータが「¥stdplugs¥stdscripts」フォルダにあります。
半径マニピュレータはかなり単純なもので、スクリプト マニピュレータ システムを記述する場合の良い例になります。
このマニピュレータのコードには次のコードが含まれます。コードの後ろにどのように動作するか詳細に記載されています。
MAXScript に、これが「RadiusManip」というスクリプト マニピュレータ プラグインであることを知らせます。「invisible:true」は、作成パネルでマニピュレータ用の作成ボタンを作らないことをシステムに伝えます。
「 canManipulate 」は、「操作」ボタンを押したときに選択されるノードごとに、各マニピュレータで呼び出されます。「 target 」パラメータは、操作する可能性のあるオブジェクトです。これは、基本オブジェクト、オブジェクト上のすべてのモディファイヤ、およびオブジェクトのノード上の変換コントローラで呼び出されます。また、変換コントローラが PRS コントローラの場合、位置、回転、およびスケール コントローラで「 canManipulate 」を呼び出します。
半径マニピュレータの場合は、「 radius 」というプロパティを持つオブジェクトを操作できます。
球のような特定のオブジェクト タイプを操作するマニピュレータを作成する場合は、次のスクリプトを使用します。
「canManipulateNode n 」という、代替ハンドラが必要になる場合もあります。これは、選択したノードをハンドラに渡すたびに渡されます。これは通常は必要ではありませんが、「 canManipulate 」に「 target 」として渡されるもの以外のノードのプロパティをマニピュレータで操作する場合は有効です。
次のハンドラは「 updateGizmos 」と呼ばれ、マニピュレータがギズモを作る必要があるとき常に呼び出されます。マニピュレータの作成時に操作中のターゲットが変わる場合は、常にこれが呼び出されます。
MAXScript は、マニピュレータの作成時に、ハンドラへの呼び出しの内部で有効な変数を設定します。その 1 つが「 target 」と呼ばれる変数で、操作対象のオブジェクト、モディファイヤ、またはコントローラになります。もう 1 つは「 this 」で、これはマニピュレータ自体のことです。これも、ギズモでフラグとして使用可能な定数値を設定します。詳細は、後で説明します。「 node 」値も使用できます。これはターゲットを含むノードです。
すべてのマニピュレータが「 updateGizmos 」ハンドラの最初に含める必要があるものは、「 this.clearGizmos() 」呼び出しです。これは現在キャッシュされているギズモをクリアします。
次に、ビューポートに表示されるギズモのセットを作成します。半径マニピュレータの場合は、操作する半径を表す単一の円を作成します。
「 manip 」は、マニピュレータから使用可能な、エクスポートされたユーティリティ インタフェース関数のセットです。詳細については、下記の参照を参照してください。この例では円を作成しています。円の中心は原点にあり、半径は操作する半径の 1.01 倍で、セグメントは 28 です。操作中のオブジェクトからギズモがほんの少しだけ突き出るように、係数「1.01」が加えられています。半径を直接使用すると、操作中のオブジェクトと同じ場所にあるため、ビューポートからは見えない場合があります。
3D ギズモは、マニピュレータのターゲットを含むノードの、ローカル座標系で定義されることに注意してください。マニピュレータの表示やヒットテスト実行時にノードを移動、回転、またはスケールすると、システムが自動的に補正を行います。
これは、特殊なフラグ値を含めずに(つまり「0」で)シェイプ ギズモをマニピュレータに追加することを、マニピュレータに伝えます。 これらのフラグすべてについては、以下で説明します。また、このコマンドは、未選択のカラーとして緑(「g」)、選択済みのカラーとして赤(「r」)を指定しています。選択済みのカラーはマウスがその上を通過する際に使用され、未選択のカラーはマウスがその上にない場合に使用されます。最後に、このメソッドは文字列値を返します。
この文字列値は、マウスがギズモの上を通過する際にツール チップとして使用されます。
通常ギズモは、メッシュ、形状(ワイヤフレーム)、テキスト、およびマーカーで構成されます。詳細は、下記の「参照」で説明されています。
次のハンドラは、「 mouseMove m which 」と呼ばれます。これは、ターゲットの操作中、マウスを移動するたびに呼び出されます。「 m 」パラメータはマウス位置のスクリーン座標を保持し、「 which 」パラメータは、ドラッグ中のギズモを示すインデックスです。ギズモは、「 updateGizmos 」で作成された順に、0 で始まる番号が付けられます。
mouseMove ハンドラは、通常、マニピュレータの実装で最も扱いにくい部分です。できるだけ、マニピュレータ ギズモがマウスの下を通るように、操作中のパラメータ値を更新する必要があります。
3 次元空間に存在するマニピュレータの場合、これは通常「 ヒットレイ 」を計算することで実行されます。ヒットレイはマウス位置を通過する 3 次元空間内のレイで、ビューの方向に移動します。
このビュー レイはこの後いくつかの平面と交差し、その交差点を使用して新しいパラメータ値が計算されます。
半径マニピュレータの場合、ここで使用している平面は XY 平面です。これは、半径円がローカル座標スペースの XY 平面にあるためです。
これにより、法線が Z 軸である平面で原点([0,0,0])を通る、「pl」が作成されます。
これをビュー レイと交差させるため、平面上で「交差」演算を使用します。
まず最初に、交差の結果のホルダに「 projectedPoint 」を設定します。戻り値「 res 」は、交差を実行したかどうかを示すブール値です。true であれば交差は実行済み、false であれば失敗であることを示します。平面がビュー レイと平行している場合は、失敗することがあります。
「 projectedPoint 」にいったん交差点ができたら、それを使って半径の新しい値を決定します。このレイでは、新しい半径として原点(「 length projectedPoint 」)からの距離を使用します。操作中の実際の半径より 1.01 倍大きいギズモを作成したため、これを補正するために 1.01 で除算してスケールします。
これで操作は終了しました。通常は、「mouseMove」ハンドラで三角関数と線形代数を使う必要があります。直接操作を行うのは、ギズモはマウスの下を直接通る必要があるという考え方からです。
スタンドアロン マニピュレータは 2D スライダに類似していますが、多少余分な作業が必要です。
この説明では SliderManip.ms のコードを使用します。
スタンドアロン マニピュレータは MAX ファイルに保存可能であるため、クラス ID が必要です。詳細は、『MAXScript リファレンス』を参照してください。ここにも「 invisible:true 」行は存在しません。これは、システムが「 Create 」パネルにこのボタンを作成することを意味します。これはヘルパー作成パネルの「 Manipulators 」セクションに配置されます。
また、オブジェクト用のパラメータ ブロックおよびロールアウト ユーザ インタフェースを定義する必要があります。定義は、他のスクリプト プラグインと同じ方法で行います。
スタンドアロン マニピュレータはそれ自体を操作するため、「 canManipulate 」ハンドラは次のようになります。
さらに、マニピュレータ作成時にマウス操作を処理する作成ツールを提供する必要があります。これは他のスクリプト プラグインとまったく同じハンドルです。
スタンドアロン マニピュレータも「 updateGizmos 」ハンドラに、特殊コードを含める必要があります。スライダの場合は次のようになります。
「 target != undefined 」は、これがマニピュレータかスタンドアロン オブジェクトかを確認するためのテストです。オブジェクトがスタンドアロンのとき、「 target 」の値は未定義で、それ自体のパラメータ ブロックから取得したパラメータ値が使われます。target が定義済みであれば、操作中であることを意味します。その場合は、操作しているターゲットからパラメータの値をコピーします。
これは、このマニピュレータが指定したターゲットを操作するかどうかを示す値を返します。
これは、このマニピュレータが指定したノードを操作するかどうかを示す値を返します。
これは、マニピュレータがギズモを構築する必要がある場合に、常に呼び出されます。これは、ツール チップ用に使われる文字列値です。空の文字列が返される場合、ツール チップは表示されません。
これは、ユーザがギズモをつかんでそれをドラッグする場合に呼び出されます。
「 m 」パラメータはマウスのスクリーン座標を保持し、「which」パラメータは、ドラッグされているギズモの 0 で始まるインデックスを示します。これが、実際の操作を処理するものです。
ユーザがギズモ上で最初にマウスをクリックするときに呼び出されます。
操作の実行後に、ユーザがマウスを放したときに呼び出されます。
マニピュレータがサポートするいくつかの組み込み関数、およびユーティリティ関数を含む 2 つのヘルパー パッケージがあります。
simpleManipulator タイプ自体が、これらの利用可能な関数を保持します。
これは、現在のギズモ キャッシュをクリアするために「updateGizmos」ハンドラの先頭で呼び出す必要があります。
これによって、メッシュ(MAXの用語ではジオメトリ)からギズモが作成されます。メッシュはどの MAX メッシュでもよく、MAXScript のメッシュ作成用のツールで作成されていてもかまいません。簡単な方法の 1 つとしては、プリミティブのインスタンスを作成し、メッシュを作成する方法があります。
フラグには、0 を設定したり、1 つまたは複数の値を設定したりすることができます。複数のフラグを適用するには、各フラグの値を加算します。
次に、すべてのフラグ、および addGizmoText、addGizmoMarker、addGizmoShape、addGizmoMesh で使用可能かどうかを示します。
ギズモを表示しないようにシステムに指示します。ヒット テストが行われますが、表示はされません。すべてに適用されます。
ギズモをヒットテストしないようにシステムに指示します。ヒット テストが行われますが、表示はされません。すべてに適用されます。
アクティブなビューポートの該当するギズモの表示とヒット テストだけを行うようシステムに通知します。
これによって、シェイプ オブジェクトからギズモが作成されます。gizmoShape は、次に説明するように、「manip」パッケージの関数を使って作成できます。
フラグには「addGizmoMesh」と同じ値をセットできるほか、さらに 2 つの値がサポートされます。
シェイプの座標を 3 次元の値ではなく、ビューポートのデバイス座標として解釈するようにシステムに指示します。値は 3 次元座標として引き続き指定されますが、「Z」座標は無視され、addGizmoMesh 以外のすべてに適用されます。
これは gizmoUseScreenSpace に似ていますが、座標は 0.0 から 1.0 までの値として指定され、各ビューポートでビューポートの幅または高さのパーセントとして解釈され、addGizmoMesh 以外のすべてに適用されます。
これによって、マーカーからギズモが作成されます。「markerType」パラメータの値は次のとおりです。
#point #hollowBox #plusSign #asterisk #xMarker #bigBox #circle #triangle #diamond #smallHollowBox #smallCircle #smallTriangle #smallDiamond #dot #smallDot
position は、3D 空間上のポイントまたは 2D の画面空間上のポイントです。フラグは、addGizmoShape でサポートされるものと同じです。
これによって、画面上にテキストのギズモが作成されます。テキストはヒットテストを行ったり、マウスで選択したりすることはできません。これは表示のためだけに使用されます。
この関数はマウスの位置をとり、ビューの方向でそのマウス位置を通るレイを返します。戻り値は、マニピュレータ ターゲットを所有するノードのローカル座標で返されます。
「manip」は、マニピュレータ用の有用なインタフェース関数のセットを含む、MAXScript の値です。manip がエクスポートする関数は次のとおりです。
これは、指定した位置、半径、セグメントを持つメッシュ球を返します。
与えられたパラメータを使用してボックス メッシュを作成します。
特定のポイントを通る指定された法線を持つ、平面オブジェクトを作成します。
与えられたパラメータを使用して、XY 平面に円シェイプを作成します。
空のギズモ シェイプを作成します。使用方法については、後述の「GizmoShape」を参照してください。
「manip.makePlaneFromNormal」から返される平面オブジェクトには、利用可能な次の関数があります。
これは、与えられたレイを平面と交差させます。成功した場合はture、失敗した場合は false を返します。成功した場合、交差点は「intersectionPoint」値で設定されます。
これは、与えられたレイに最も直交する平面を返します。つまり、ビュー方向に対して最も「四角い」平面です。
マニピュレータが、レイの投影に、2 つの別々の平面の間を選択することもあります。通常は、直接的にビュー レイに面する平面に投影するのが最善で、この関数がそれを決定します。使用例は、「UVWManip.ms」を参照してください。