コントローラは 3ds Max での、アニメーション タスクを処理するプラグインです。これらは通常、トラック ビューまたは[モーション] (Motion)パネルのオブジェクトに割り当てられます。また、プログラムによって割り当てることもできます(このセクションの後で説明する例を参照)。
MAXScript のスクリプト定義アニメーション コントローラはパラメータ ブロックとロールアウトをサポートします。
スクリプト定義アニメーション プラグイン コントローラでは次のスーパークラスが定義されます。
スクリプト定義アニメーション コントローラ プラグインには、少なくとも getValue
イベント ハンドラが 1 つ必要です。その他のすべてのイベント ハンドラはオプションです。一時保存/復元システムに関連付けられているハンドラは通常実装されません。「一時保存と復元システム」の説明を参照してください。
コントローラのインスタンスがシーン内で作成されると呼び出されます。このハンドラは、コントローラの状態変数を設定するために使用されます(以下の「ローカル変数」を参照)。on create
ハンドラの詳細については、「スクリプト定義プラグイン Clauses_TOPIC_740」の「イベント ハンドラ」セクションを参照してください。
コントローラのタイプに応じて値、タイプを返します。
コントローラが UI、MAXScript あるいは他の max コードのいずれかによって値に設定されると呼び出されます。このハンドラはオプションです。
setValue
を相対モード(これは method == #relative
でテストできます)で使用した場合、relVal
には現在の値からのデルタが含まれます。absVal
はユーザのために事前に計算された絶対値です。setValue
を絶対モード(method == #absolute
)で使用した場合、relVal
と absVal.
は同じです。
commit
パラメータは、コントローラが値の設定を持続するか、単に値の設定をキャッシュするかを指定します。 false の場合、commitValue
および restoreValue
ハンドラが必要になります。 ただし、知られている限りでは、現在のプラグインがこの値を false として渡すことはないので、これらのハンドラは不要です。詳細については、以下の「一時保存と復元システム」を参照してください。
ユーザがビューポートにマウスを置いた状態でコントローラの変更を開始すると呼び出されます。たとえば、ノードをビューポート内で移動すると、これは変換関連の各コントローラで呼び出されます。
このハンドラはオプションで、主に一時保存/復元システムをサポートします。
ユーザがビューポートにマウスを置いた状態でコントローラの変更を終了すると呼び出されます。たとえば、ノードをビューポート内で移動すると、これは変換関連の各コントローラで呼び出されます。
mouseCycleCompleted
は対応する mouseCycleStarted
なしで呼び出すことができる場合があります。たとえば、トラック ビューでコントローラのキーを移動する場合です。このハンドラはオプションで、主に一時保存/復元システムをサポートします。
コントローラの値の変更を開始すると呼び出されます。
このハンドラはオプションで、主に一時保存/復元システムをサポートします。
コントローラの値の変更を終了すると呼び出されます。
このハンドラはオプションで、主に一時保存/復元システムをサポートします。
ユーザがコントローラの設定値を元に戻すなど、コントローラがアンドゥ システムによって初期の値にリセットされると呼び出されます。
このハンドラはオプションで、主に一時保存/復元システムをサポートします。
コントローラがアンドゥ システムによって後者の値に設定されると呼び出されます。これはユーザがコントローラの設定値のやり直しを実行したときに呼び出されます。
このハンドラはオプションで、主に一時保存/復元システムをサポートします。
setValue
ハンドラの commit
パラメータが false の場合に呼び出されます。これはコントローラがキャッシュされた値から値の設定を持続することを意味します。
このハンドラはオプションで、主に一時保存/復元システムをサポートします。
setValue
ハンドラの commit
パラメータが false の場合に呼び出されます。これはコントローラがキャッシュされた値を使用しないことを意味します。
このハンドラはオプションで、主に一時保存/復元システムをサポートします。
setValue
および commitValue
/restoreValue
ハンドラの commit パラメータは「内部の」一時保存と復元メカニズムの一部です。コントローラの SetValue() メソッドが呼び出されると、コミット パラメータが true の場合、コントローラは現在の時刻のコントローラの値をそのキャッシュに保存し、さらに値を「コミット」します。たとえば、キーフレーム コントローラの場合、これはキーを保存します。設定値がコミットされないと、RestoreValue()
が呼び出されて前の値を復元します。これは、現在のキャッシュの値を SetValue()
が最後に呼び出される前に設定された値に復元します。
setValue
へのコミット パラメータが現在のプラグインによって false として渡されることはないので、コントローラのスクリプト定義プラグインのタイプの将来の反復では削除される場合があります。ただし、コントローラ フレームワークはこの内部の一時保存と復元メカニズムを提供し、サードパーティのプラグインによって使用することができます。以下の FloatController
のスクリプト例には、このメカニズムが使用される場合の検出と情報表示が含まれます。
スクリプト定義アニメーション プラグイン コントローラには次のローカル変数を使用できます。
コントローラがリーフ コントローラであるかどうかを示します。コントローラがリーフ コントローラの場合、定義上はサブコントローラもリファレンスもありません。__サブコントローラがない場合、コントローラは true を返します。たとえば、PRS コントローラはリーフ コントローラではありません(位置、回転、およびスケールのサブコントローラがあるため)が、単純なキーフレーム フロート コントローラはリーフ コントローラです。
イーズ/マルチプライヤ カーブおよび範囲外のタイプは、リーフ コントローラにのみ適用することができます。ツリービューで使用できるフィルタは、コントローラがリーフ コントローラかどうかによって異なります。この変数の既定値は false です。この変数は通常「on create」ハンドラで設定されます。
コントローラが適用されるパラメータにリンクされた UI 要素(スピナーまたはスライダ)が有効かどうかを示します。この変数が false の場合、UI 要素は無効になります。setValue ハンドラが定義されていない場合、この変数の既定値は false で、定義されている場合は true です。 この変数を設定する場合、通常は「on create」ハンドラに設定します。
setValue ハンドラ内で使用します。呼び出しが #relative または #absolute のどちらのメソッドで発生したかを指定します。
この変数は変換関連のスクリプト定義プラグイン コントローラで使用され、それ以外のスクリプト定義プラグイン コントローラでは「未定義」です。on getValue ハンドラ内で使用します。 この変数には、method == #relative のときに変換関連のスクリプト定義プラグイン コントローラ(positionController、rotationController、scaleController、transformController)の on getValue ハンドラを評価する場合の(修正された)親ノード変換が含まれます。 親の変換マトリクスのコピーはノードの変換コントローラに渡され、変換コントローラおよびそのサブコントローラは Matrix3 の値を操作および修正することができます。この値は、コントローラのパイプラインを通過する現在の変換の値を表します。
たとえば PRS コントローラでは、位置コントローラが通常 Point3 の値を使用して Matrix3 の値を変換し、修正された Matrix3 の値は回転コントローラに渡されます。これは通常 Matrix3 の値を回転させ、次に修正された Matrix3 の値がスケール コントローラに渡されます。この値は読み取り専用です。スクリプト定義プラグインの C++ 実装は getValue ハンドラから返される値に基づいてこの Matrix3 の値を操作します。
変換関連のコントローラの on getValue ハンドラで method == #absolute の場合、コントローラは直接評価され(たとえば MaxScript の
この変数はスクリプト定義プラグイン コントローラの現在の値のキャッシュをコントロールします。通常、コントローラはコントローラの妥当性間隔と現在の値をキャッシュします。getValue 呼び出しの発生時間の値が妥当性間隔の範囲内であれば、キャッシュされた現在の値は getValue ハンドラの評価なしで返されます。 getValue ハンドラの呼び出しの戻り値が親の変換値に依存する場合、親ノードが変換される場合の結果が不正になります。それは、親ノードからすべての子ノードの変換関連のコントローラに通知が送信されず、それらのコントローラが無効になるためです。 この変数が true である場合、キャッシュされた現在の値は使用されず、getValue ハンドラが常に呼び出されます。 その結果さらに多くの評価が発生します。そのため、結果が親の変換に依存する変換関連のスクリプト定義プラグイン コントローラの場合のみ true に設定します。この変数の既定値は false です。この変数は通常 create ハンドラで設定されます。
フロート コントローラ プラグインのタイプは浮動小数点値をコントロールします。以下の例ではフロートにオフセット値を追加し、テスト ケースはオブジェクトの X 位置をコントロールします。このサンプルは、パラメータ ブロックとロールアウト UI の実装を示しています。これは、コントロールされるオブジェクトを選択したときに[モーション] (Motion)パネルに表示されます。また、commitValue
、restoreValue
および holdBegin
/holdEnd
/holdRestore
/holdRedo
ハンドラに実装することによって一時保存/復元/やり直しシステムを使用する方法も示します。上の「一時保存と復元システム」で述べたように、現在出荷されているプラグインでこのメカニズムを使用しているものはないため、これらのハンドラは必要ではありません。ただしサードパーティのプラグインではこのメカニズムを使用するものがあるかもしれません。
plugin FloatController FloatController_example
name:"FloatController Example"
classID:#(0x47db14fe, 0x4e9b5f90)
(
local first = true -- used for debug tracing of 'commit' handling
local useCachedValue = false -- set when have SetValue with commit == false
local cachedValue = undefined -- set when have SetValue with commit == false
local inMouseCycle = false -- true when within mouseCycleStarted/mouseCycleCompleted
local inMouseCycleControllerAssigned = false -- true when controller assigned within mouseCycleStarted/mouseCycleCompleted
local inMouseCycleSetValue = false -- true when setValue w/o holdRestore occurred within mouseCycleStarted/mouseCycleCompleted
parameters pblock rollout:params
(
value type:#float animatable:true ui:value
valueController type:#maxobject
)
rollout params "FloatController Test Parameters"
(
Spinner value "Value:"
)
on getValue do
(
format "getValue - useCachedValue: %; value: %; cachedValue: %\n" useCachedValue value cachedValue
if useCachedValue then cachedValue else value
)
on setValue val relVal commit do
(
format "setValue - val: %; commit: %; useCachedValue: %; value: %; cachedValue: %\n" val commit useCachedValue value cachedValue
if not commit and first do
(
print (CaptureCallStack())
first = false
messagebox "setValue called with commit = false - see listener for stack trace"
)
if commit then
(
useCachedValue = false
cachedValue = undefined
if inMouseCycle do
inMouseCycleSetValue = true
value = val
)
else
(
useCachedValue = true
cachedValue = val
)
SetControllerValue valueController val commit #absolute
)
on commitValue do
(
format "commitValue - useCachedValue: %; value: %; cachedValue: %\n" useCachedValue value cachedValue
if first do
(
print (CaptureCallStack())
first = false
messagebox "commitValue called - see listener for stack trace"
)
useCachedValue = false
value = cachedValue
cachedValue = undefined
CommitControllerValue valueController
)
on restoreValue do
(
format "restoreValue - useCachedValue: %; value: %; cachedValue: %\n" useCachedValue value cachedValue
if first do
(
print (CaptureCallStack())
first = false
messagebox "restoreValue called - see listener for stack trace"
)
useCachedValue = false
cachedValue = undefined
RestoreControllerValue valueController
)
on mouseCycleStarted do
(
format "mouseCycleStarted - holding: %; value.controller: %\n" (theHold.Holding()) value.controller
inMouseCycle = true
inMouseCycleControllerAssigned = false
)
on mouseCycleCompleted do
(
format "mouseCycleCompleted - holding: %; value.controller: %\n" (theHold.Holding()) value.controller
inMouseCycle = false
inMouseCycleControllerAssigned = false
)
on holdBegin do
(
format "holdBegin\n"
if inMouseCycle and animateMode and value.controller == undefined and (currenttime != 0) do
(
inMouseCycleControllerAssigned = true
with undo off value.controller = NewDefaultFloatController()
)
)
on holdEnd do
(
format "holdEnd - inMouseCycleControllerAssigned: %; inMouseCycleSetValue: %\n" inMouseCycleControllerAssigned inMouseCycleSetValue
if inMouseCycleControllerAssigned and not inMouseCycleSetValue do
with undo off value.controller = undefined
)
on holdRestore do
(
format "holdRestore\n"
if inMouseCycle do
inMouseCycleSetValue = false
)
on holdRedo do format "holdRedo\n"
on create do
(
valueController = NewDefaultFloatController()
isLeaf=true
)
)
/* Test case:
t = teapot isselected:true
t.radius.controller = FloatController_test()
t.pos.controller.x_position.controller = FloatController_example()
*/
これは、同じフロート コントローラで一時保存/復元システムを実装しないより典型的なバージョンです。また、手続き型コントローラを作成する方法も示します。この場合、コントロールされるフロート値を現在の時間とオフセットで修正しています。プラグイン定義で usePBValidity:false
が使用されていることに注意してください。
plugin FloatController FloatController_simplified_example
name:"Simplified FloatController Example"
usePBValidity:false -- false because time dependent
classID:#(0xc1dbcd6, 0x70ecb08a)
(
parameters pblock rollout:params
(
offset_value type:#float animatable:true ui:offset_value
valueController type:#maxobject subAnim:true
)
rollout params "FloatController Test Parameters"
(
Spinner offset_value "Offset Value:" range:[0, 1e9, 40]
)
on getValue do
(
valueController.value +offset_value + currentTime as integer / framerate
)
on setValue val relVal commit do
(
val -= ( offset_value+ currentTime as integer / framerate)
SetControllerValue valueController val commit #absolute
)
on create do
(
valueController = NewDefaultFloatController()
isLeaf=true
)
)
/* Test case:
t = teapot isselected:true
t.radius.controller = c = FloatController_simplified_example()
c.isKeyable = true
c.isleaf = false
*/
Point3Controller プラグインのタイプは、Point3 値をコントロールします。これは位置の値をコントロールしないことに注意してください。代わりに PositionController
(以下を参照)を使用する必要があります。このコントローラは座標オフセットなどに使用することができます。次の例では、コントローラはマテリアルの拡散反射光マップ座標に適用されます。
plugin Point3Controller Point3Controller_example
name:"Point3Controller Example"
classID:#(0x47db14ff, 0x4e9b5f9f)
(
parameters pblock
(
offset_value type:#point3 animatable:true
valueController type:#maxobject subAnim:true
)
on getValue do
(
valueController.value + offset_value
)
on setValue val relVal commit do
(
val -= offset_value
SetControllerValue valueController val commit #absolute
)
on create do
(
valueController = NewDefaultPoint3Controller()
isLeaf=true
)
)
/* Test case:
t = teapot isselected:true
t.material = standard diffusemap:(cellular())
t.material.diffusemap.coords.offset.controller = Point3Controller_example()
c = t.material.diffusemap.coords.offset.controller
meditmaterials[1] = t.material.diffusemap
max mtledit
t.pos.controller = Point3Controller_example() -- will give: -- Runtime error: Incompatible controller type for property: position
*/
このプラグイン コントローラのタイプは、シェーダの 4D カラー スペースなど Point4 の値をコントロールします。
この例では、オフセット値を Point4 値に追加します。
plugin Point4Controller Point4Controller_example
name:"Point4Controller Example"
classID:#(0x47db14ff, 0x4e9b5f9f)
(
parameters pblock
(
offset_value type:#point4 animatable:true
valueController type:#maxobject subAnim:true
)
on getValue do
(
valueController.value + offset_value
)
on setValue val relVal commit do
(
val -= offset_value
SetControllerValue valueController val commit #absolute
)
on create do
(
valueController = NewDefaultPoint4Controller()
isLeaf=true
)
)
/* Test case:
c = Point4Controller_example()
at time 100 with animate on c.offset_value =[100,200,300,400]
slidertime = 50f
c.offset_value
c.value += [10,20,30,40]
c.offset_value
c.value
c.valueController.value
*/
ColorController プラグインは、カラー値のアニメーションをコントロールします。この例では、コントローラはカラー値にオフセットを追加し、コントローラはマテリアルの拡散反射光カラーに適用されます。
plugin ColorController ColorController_example
name:"ColorController Example"
classID:#(0x47db14ba, 0x4e9b5f9f)
(
parameters pblock
(
offset_value type:#color animatable:true
valueController type:#maxobject subAnim:true
)
on getValue do
(
valueController.value + offset_value
)
on setValue val relVal commit do
(
val -= offset_value
SetControllerValue valueController val commit #absolute
)
on create do
(
valueController = NewDefaultColorController()
isLeaf=true
)
)
/* Test case:
t = teapot isselected:true
t.material = standard ()
t.material.diffuse.controller = ColorController_example()
c = t.material.diffuse.controller
meditmaterials[1] = t.material
max mtledit
*/
PositionController プラグインのタイプはアニメート可能な位置をコントロールします。以下の例では、コントローラはオフセットをコントロールされる Point3 の値に追加します。この値はティーポット オブジェクトの位置に適用されます。
plugin PositionController PositionController_example
name:"PositionController Example"
classID:#(0x47db14fa, 0x4e9b5f9f)
(
parameters pblock
(
offset_value type:#point3 animatable:true
valueController type:#maxobject subAnim:true
)
on getValue do
(
res = valueController.value + offset_value
res
)
on setValue val relVal commit do
(
val -= offset_value
format "committing val: %\n" val
SetControllerValue valueController val commit #absolute
)
on create do
(
valueController = NewDefaultPositionController()
isLeaf=true
)
)
/* Test case:
t = teapot isselected:true
t.pos.controller = PositionController_example()
c = t.pos.controller
*/
回転コントローラ プラグインのタイプは、シーン オブジェクトの回転の値をコントロールします。以下のコントローラの例では、回転の値は Matrix3 の値の回転の部分として格納されます。コントローラはオフセットをコントロールされる値に追加します。この値はオブジェクトの回転に適用されます。
plugin RotationController RotationController_example
name:"RotationController Example"
classID:#(0x47db14ac, 0x4e9b5f9f)
(
parameters pblock
(
offset_value type:#matrix3 animatable:true
valueController type:#maxobject subAnim:true
)
on getValue do
(
res = valueController.value + offset_value.rotationpart
res
)
on setValue val relVal commit do
(
val -= offset_value.rotationpart
SetControllerValue valueController (val as matrix3) commit #absolute
)
on create do
(
valueController = NewDefaultRotationController()
isLeaf=true
)
)
/* Test case:
t = teapot isselected:true
t.rotation.controller = RotationController_example()
c = t.rotation.controller
*/
ScaleController タイプのプラグインは、スケール値を Point3 としてコントロールします。以下の例では、コントローラはオフセットをコントロールされる値に追加します。
plugin ScaleController ScaleController_example
name:"ScaleController Example"
classID:#(0x7fa4db14, 0x4e5f9b9f)
(
parameters pblock
(
offset_value type:#point3 animatable:true
valueController type:#maxobject subAnim:true
)
on getValue do
(
res = valueController.value + offset_value
res
)
on setValue val relVal commit do
(
val -= offset_value
SetControllerValue valueController val commit #absolute
)
on create do
(
valueController = NewDefaultScaleController()
isLeaf=true
)
)
/* Test case:
t = teapot isselected:true
t.scale.controller = ScaleController_example()
c = t.scale.controller
c.value = [.9,.9,.9]
*/
TransformController プラグインは変換値(Matrix3)をコントロールします。この例では、コントロールされる値にオフセットを追加します。
plugin TransformController TransformController_example
name:"TransformController Example"
classID:#(0x47db1cad, 0x4e9b5f9c)
(
parameters pblock
(
offset_value type:#matrix3
valueController type:#maxobject subAnim:true
)
on getValue do
(
res = valueController.value * offset_value
res
)
on setValue val relVal commit do
(
val = val * inverse offset_value
SetControllerValue valueController val commit #absolute
)
on create do
(
valueController = NewDefaultMatrix3Controller()
isLeaf=true
)
)
/* Test case:
t = teapot isselected:true
t.transform.controller = TransformController_example()
c = t.transform.controller
at time 100 c.value
c.value = matrix3 1
*/