マウス ツール定義の <tool_body>
は、次のような一連のツール句で構成されます。
<tool_body> ::= { <tool_clause> }+
ツール句は、次の 2 つの基本事項のうちの 1 つであり、ツールのコンポーネントを定義します。
ローカル変数、関数、および構造体とは、スコープがツールである変数、関数または構造体のことです。<tool_body>
は独自のローカル スコープでコンパイルされ、ローカルはツールのスコープ内だけで可視です。ツール ローカルは、通常の(スタック ベースの)ローカルと多少異なるヒープ ベースのローカルです。通常のローカルは現在のスコープ内で可視であり、そのスコープの実行が終了するまでの寿命があります。ヒープ ベースのローカルは、現在のスコープ内でのみ可視となっていますが、寿命はこのローカルが定義されているトップ レベルの式の寿命と同じです。ツールのローカルは、ツールを最初に実行したときに作成され、そのツールが再定義されない限りヒープ内に永続的に保持されます。つまり、ツールの実行に関係なく保持される、ツールで作成されたロールアウトなどは、これらのローカルを参照でき、ローカルはそのまま保持されます。ツールを実行するたびに、そのローカル変数は undefined
値あるいは指定された初期値に初期化されます。たとえば、ツール内でロールアウトを作成することができ、ロールアウトのイベント ハンドラはツール内で定義されたローカルにアクセスできます。ロールアウトがツールのスコープ内で実行されているためです。ツールのローカルは、別のユーティリティやリスナーからはアクセスできません。これは、別のツールのスコープ内では実行されていないためです。詳細については、「変数のスコープ」を参照してください。
イベント ハンドラは、特定のイベントに関連付けられた特殊な関数です。イベント ハンドラでは、ユーザがマウスの左ボタンまたは右ボタンをクリック、マウスを移動、またはツールを開始または終了したときに実行する処理を指定します。これらのアクションによって名前付きイベントが生成され、このイベントに指定したオプションのイベント ハンドラがアクションの発生時に呼び出されます。
<tool_clause>
は、次のように定義されます。
<tool_clause> ::= <local_variable_decl> | <local_function_decl> | <local_struct_decl> | <event_handler>
ローカル
<local_variable_decl>
、<local_function_decl>
、<local_struct_decl>
は、MAXScript 内のローカル変数、関数、構造体の定義とまったく同義です。
<local_variable_decl> ::= local <decl> { , <decl> }
<decl> ::= <name> [ = <expr> ] -- optional initial value
<local_function_decl> ::= [ mapped ](function | fn ) <name> { <argument> } = <expr>
<local_struct_decl> ::+ struct <name> ( <member> { , <member> } )
<member> ::= ( <name> [ = <expr> ] | <local_function_decl> )
グローバル変数は、ツール句としては宣言できませんが、イベント ハンドラ スクリプト内で宣言できます。変数名にグローバル変数を必ず参照させる必要がある場合は、スクリプトでツールを定義する直前に、変数名をグローバルとして宣言します。
スクリプトを作成するときは、ローカル変数およびグローバル変数を明示的に宣言することをお勧めします。暗示的な宣言は簡易的に提供されるものであり、通常、リスナーでインタラクティブに作業する場合や短いスクリプトを作成する場合に使用します。長いスクリプトを作成する場合は、変数を明示的に宣言するとエラーを軽減し、コードが読みやすくなります。また、特にグローバル変数を必要な場合を除き、すべての変数をローカルとして宣言することをお勧めします。この理由については、「変数のスコープ」を参照してください。
ツールの関数やイベント ハンドラ内では、13 個の定義済みローカル変数にアクセスできます。各変数は、直前に発生したマウス アクションに関する有用な値を保持します。
viewPoint Point2
ビューポートのピクセル座標による現在のマウスの位置です。
worldPoint Point3
ワールド座標のアクティブなグリッドに投影された現在のマウスの位置です。
worldDist Point3
ワールド座標における、前回のクリック位置から今回のクリック位置への x、y、z の距離です。
worldAngle Point3
ワールド座標における前回のクリック位置から今回のクリック位置への z、y、z の軸を基準にした角度です。
gridPoint Point3
アクティブなグリッドの座標系内のアクティブなグリッドに投影された現在のマウスの位置です。アクティブなグリッドがホーム グリッドの場合、座標系は現在のビューポートでアクティブになっているホーム グリッド面になります(これは作図平面です)。詳細は、以下のグリッド値とワールド値に関する説明を参照してください。
gridDist Point3
アクティブなグリッドの座標系内の前回のクリック位置から今回のクリック位置への x、y、z の距離です。アクティブなグリッドがホーム グリッドの場合、座標系は現在のビューポートでアクティブになっているホーム グリッド面になります(これは作図平面です)。詳細は、以下のグリッド値とワールド値に関する説明を参照してください。
gridAngle Point3
アクティブなグリッドの座標における前回のクリック位置から今回のクリック位置への z、y、z の軸を基準にした角度です。アクティブなグリッドがホーム グリッドの場合、座標系は現在のビューポートでアクティブになっているホーム グリッド面になります(これは作図平面です)。詳細は、以下のグリッド値とワールド値に関する説明を参照してください。
shiftKey Boolean
true
: Shift キーが押されている場合です。
ctrlKey Boolean
true
: Ctrl キーが押されている場合です。
altKey Boolean
true
: Alt キーが押されている場合です。
lButton Boolean
true
: マウスの左ボタンが押されている場合です。
mButton Boolean
true
: マウスの中央のボタンが押されている場合です。
rButton Boolean
true
: マウスの右ボタンが押されている場合です。
レベル 5 のスクリプト化されたプラグインでマウス ツールの作成を使用する場合は、次のローカル変数にもアクセスできます。
nodeTM Matrix3
現在作成中のノードの変換への読み込みおよび書き込みアクセスを提供します。この値は、現在のグリッド座標系にあります。
詳細は、「スクリプト プラグイン」を参照してください。
SimpleObject のスクリプト プラグインを記述する場合、対応するワールド座標値ではなく、必ず gridPoint
、gridDist
、gridAngle
の値を使用してください。これは、SimpleObject のスクリプト プラグインでは、オブジェクトの作成がアクティブなグリッドの座標系で管理されるためです。
gridDist
での .X および .Y コンポーネントは、先にクリックしたポイントと現在のグリッド平面上の現在のマウス ポイント間のデルタ X および デルタ Y です。Z コンポーネントは、現在の Y スクリーン座標からグリッド上でクリックされた最後の点である Z ベクトル(グリッド座標系上)への投影です。この .Z 値は、投影された Z ベクトルの高さです。非直行のビューポートでは、これは予想どおりの結果になりますが、直行ビューポート(グリッドの XY 平面にドラッグする場所)では、この値は常に gridDist.y
と同じ値になります。グリッド上でオブジェクトの一部を構築するために gridDist 値を使用する場合や、最後のポイントから現在のグリッドまでの距離を決定するために gridDist 値を使用する場合は、.X と .Y コンポーネントだけを使用してください。
例
side1Len = gridDist.x
side2Len = gridDist.y
dist=length [gridDist.x,gridDist.y]
現在のグリッドの高さを指定する場合は、通常、.Z コンポーネントを使用します。
例
height = gridDist.z
worldDist
での動作は gridDist
での動作と似ていますが、投影コンポーネントはビューポートの作図平面上に従属しています。トップ、ボトム、および非直行ビューポートでは、.Z コンポーネント値が投影の高さです。レフトおよびライト ビューポートでは、.X コンポーネント値が投影の高さです。フロントおよびバック ビューポートでは、.Y コンポーネント値が投影の高さです。
3ds Max のユーザインタフェースでノードを作成するときは、ノードのローカル Z 軸は、作図平面に対して垂直になります。MAXScript を使ってノードを作成するときは、既定値ではノードのローカル Z 軸はワールド座標の Z 軸と同じ向きになります。SimpleObject スクリプト プラグイン以外のツールでノードを作成するときに、3ds Max の動作を二重化したい場合は、作図平面の向きを考慮する必要があります。簡単な方法は、ノードを coordsys grid
コンテキストに作成し、そのノードの位置をグリッドの座標系で指定します。次のスクリプトに例を示します。
POINT CREATOR
tool PointCreator
(
local p, createpoint
-- define a function to perform actual node creation. Setting coordsys to
-- ’r;grid’ in order for the alignment of the node’s local Z axis to be
-- perpendicular to the construction grid
fn createpoint = in coordsys grid p=point pos:gridPoint
--
-- set up so that a node is created on a mouse button down, move node
-- drag, release node at mouse button up.
--
-- if clickno == 1, then we are at first mouse click, which is a mouse
-- button down. If clickno != 1, at following mouse button up.
on mousePoint clickno do
(
if clickno == 1
then createPoint()
-- if p == undefined, then clicked twice without mouse movement
-- (double clicked). No point object present, so just ignore this click.
else if p != undefined do (p.pos=worldPoint;p=undefined)
)
-- if p != undefined, we are moving a previously created node
-- if p == undefined, and left mouse button is down, create a node
on mouseMove clickno do
(
if p != undefined
then p.pos=worldPoint
else if lbutton do createPoint()
)
)
-- start the tool. No exit condition defined, so right-click to exit.
startTool PointCreator
イベント ハンドラ
<event_handler>
は、ユーザがビューポート内でマウスの左ボタンまたは右ボタンをクリック、あるいはツールを開始または終了した場合に実行する処理を指定する特別な関数の定義です。このユーザ アクションは名前付きのイベントおよびアクションが発生するときに呼び出されるイベントを指定するイベント ハンドラを呼び出します。次のイベント ハンドラを使用できます。
on start do <expr>
ツールの起動時に呼び出されます。
on stop do <expr>
ツールの終了時に呼び出されます。
on freeMove do <expr>
マウスが最初のクリックの前に移動するときに呼び出されます。
on mousePoint <arg> do <expr>
マウスをクリックするたびに呼び出されます。パラメータ arg
には、クリックの数が含まれます。
on mouseMove <arg> do <expr>
最初のクリックの後にマウスが移動すると呼び出されます。
on mouseAbort <arg> do <expr>
ユーザがマウスの右ボタンをクリックしてキャンセルした場合、または[Esc]を押した場合に呼び出されます。
<arg>
パラメータは、現在のマウス クリックを示しています。各マウス クリックは、実際には最初のクリックではなく、マウスのボタンを放したときのみマウス クリックのイベントとなります。マウスのクリック、ドラッグ、ボタンを放す操作と移動を順に行い、次に再びクリック、ドラッグ、およびボタンを放す操作を行うと、最初のクリックや最初と 2 回目のボタンを放す操作のときに on mousePoint
イベント ハンドラが合計 3 回呼び出され、<arg>
の値はそれぞれ 1、2、および 3 になります。マウス クリックのカウンタは、on mousePoint
イベント ハンドラの処理後に値が増加します。また、<arg>
のパラメータ(mouseMove
および mouseAbort
のイベント ハンドラに対応)は、次のマウス クリックのクリック カウントを指定します。上の例では、最初のクリックから最初のボタンを放すまでの間にドラッグ操作を行った場合、mouseMove
イベント ハンドラの <arg>
値は 2 になります。後の移動、クリック、およびドラッグ時の値は 3 になります。
3ds Max 6 以降では、マウス ツールの実行時に、作図平面がエッジ上にあるビューポートでクリックすると、値 #abort
を返してツールが終了します。
次のスクリプトは、さまざまなイベント ハンドラがいつ呼び出されるかを示します。スクリプトを実行して、ビューポート内をドラッグしてみてください。マウスの右ボタンをクリックするか、[Esc]を押すと、ツールを終了できます。
例:
tool foo
(
on freeMove do print "Free Moving"
on mousePoint clickno do format "Point: %\n" clickno
on mouseAbort clickno do format "Abort: %\n" clickno
on mouseMove clickno do format "Moving: %\n" clickno
on start do print "Starting"
)
startTool foo prompt:"Hello!"
すべてのマウス アクションのイベントハンドラは、特殊な値 #stop
を返します。次の mousePoint
イベント ハンドラの例では、最初のクリックでボックスが作成され、放すと(2 回目のクリックで)ツールが終了します。
例:
on mousePoint clickno do
if clickno == 1
then b = box pos:worldPoint
else #stop
次のスクリプトでは、マウスをクリックするとマウスの位置に 3 つのスポット ライトを作成する機能が実装されます。マウスのボタンを押しながらドラッグして、従来型の主光線、バック ライト、補助光の位置を決定します。[Shift]キーを押しながらドラッグすると、補助光が反転します。マウス ボタンを放し、マウスを移動してライトの高さを変更します。ライトを適当な高さに移動したら、マウスをクリックします。バック ライトは主光線の 1.5 倍の高さに、補助光は 0.75 倍の高さに設定されます。
このツールを開始するには、次のスクリプトを使用します
startTool three_lights
次に、ビューポートの 1 つにドラッグします。
例:
tool three_lights
(
local key, fill, back, targ
on mousePoint click do coordsys grid
(
if click == 1 then -- create key, back & fill lights at mousedown
(
targ = targetobject pos:gridPoint
key = targetspot pos:gridPoint name:"key"target:targ
back = targetspot pos:gridPoint name:"back"target:targ
fill = targetspot pos:gridPoint name:"fill"target:targ
)
if click == 3 then #stop
)
on mouseMove click do
(
if click == 2 then -- drag out & round on x-y plane
(
coordsys grid key.pos = gridPoint
coordsys targ back.pos = - key.pos
local p = if shiftKey then 90 else -90
coordsys targ fill.pos = key.pos * ((eulerangles 0 0 p) as quat)
)
else if click == 3 then -- drag up to elevate lights
(
in coordsys targ
(
local Z = gridDist.z
key.pos.z = Z
back.pos.z = Z * 1.5
fill.pos.z = Z * 0.5
)
)
)
)