この記事はMaya Advent Calender 2020の3日目の記事です。
AdventCalenderに初めて参加させていただきます。
#はじめに
Rampのカーブを入力として利用したツールを制作する為に調べました。
今回は、PySideではなくmayaコマンドでGUIを作っています。
#サンプル
下記のコードを実行すると、GUIが表示されます。
import maya.cmds as cmds
import maya.mel as mel
class rampWindow(object):
@classmethod
def showUI(cls):
"""
showUI
UIを表示させます。
"""
win = cls()
win.create()
return win
def deleteUI(self, *args):
"""
deleteUI
UIを削除します。
rampアトリビュート用のNullを削除します。
"""
cmds.deleteUI(self.window, window=True)
self.deleteRampNode()
def deleteRampNode(self, *args):
"""
deleteRampNode
rampアトリビュート用のNullを削除します。
ウィンドウの×を押した時のコマンド用。
"""
if cmds.ls(self.nodeName):
cmds.delete( self.nodeName )
def __init__(self):
"""
__init__
初期化。
"""
self.window = 'rampWindow'
self.title = 'rampWindow'
self.width=200
self.rampName = "ramp"
self.nodeName = "rampNull"
def create(self):
"""
create
レイアウト作成。
"""
# 多重ウィンドウ対応
if cmds.window(self.window, exists=True):
self.deleteUI()
# rampアトリビュート用Nullを作成
cmds.group(em=True, n=self.nodeName)
createRampAttrbute( self.nodeName, self.rampName )
# ウィンドウ作成
self.window = cmds.window( self.window, t=self.title, w=self.width, cc=self.deleteRampNode )
cmds.columnLayout()
# Layout Frame Range
rampLayout( self.nodeName, self.rampName )
cmds.showWindow( )
def createRampAttrbute( nodeName, rampName ):
"""
createRampAttrbute
RampAttrbuteを設定します。
Args:
String nodeName : RampAttrbuteの追加するノード名
String rampName : RampAttrbute名
"""
cmds.addAttr( nodeName, ln=rampName, at='compound', nc=3, m=True)
cmds.addAttr( nodeName, ln='ramp_Position', at='float', p=rampName, dv=-1)
cmds.addAttr( nodeName, ln='ramp_FloatValue', at='float', p=rampName, dv=-1)
cmds.addAttr( nodeName, ln='ramp_Interp', at='enum', en='None:Linear:Smooth:Spline', dv=1, min=0, max=3, p=rampName)
cmds.setAttr( '{0}.{1}[0]'.format(nodeName, rampName), 0, 1, 2)
cmds.setAttr( '{0}.{1}[1]'.format(nodeName, rampName), 1, 1, 2)
def rampLayout( nodeName, rampName ):
"""
rampLayout
rampをレイアウトします。
Args:
String nodeName : RampAttrbuteの追加されているノード名
String rampName : RampAttrbute名
"""
mel.eval('if (! exists("AEmakeLargeRamp")) source AEaddRampControl')
mel.eval('AEmakeLargeRamp("{0}.{1}", 0, 0, 0, 0, 0)'.format(nodeName, rampName))
if __name__ == '__main__':
rampWindow.showUI()
#解説
- レイアウトを行う前に、GUIで使用するRampのパラメータを保持する為にNullを用意しています。
そのNullにRampアトリビュートを追加します。
# rampアトリビュート用Nullを作成
cmds.group(em=True, n=self.nodeName)
createRampAttrbute( self.nodeName, self.rampName )
- ウィンドウを用意し、Rampをレイアウトします。
mel.eval('if (! exists("AEmakeLargeRamp")) source AEaddRampControl')
mel.eval('AEmakeLargeRamp("{0}.{1}", 0, 0, 0, 0, 0)'.format(nodeName, rampName))
- AEmakeLargeRamp コマンド。引数が6個必要ですが、rampのアトリビュート名を指定すれば、後は0で問題ないと思います。
AEaddRampControl.mel
global proc AEmakeLargeRamp( string $nodeAttr,
int $bound,
int $indent,
int $staticEntries,
int $staticPositions,
int $adaptiveScaling )
#おまけ
実行ボタンを起動しランプの値をとる際には、Fit関数を用意すると便利です。
この関数で、パラメータの「開始値1・終了値1」間の変化を、「開始2・終了2」間の変化にマッピングします。
HoudiniのVEXライクな関数を作ってみました。
def fit(parameter, startValue1, endValue1, startValue2=0, endValue2=1):
"""
fit
値の範囲を別の値にマッピングする。
Args:
Float parameter : パラメータ
Float startValue1 : 開始値1
Float endValue1 : 終了値1
Float startValue2 : 開始値2
Float endValue2 : 終了値2
Returns:
Float value : マッピングされたの値
"""
if parameter < startValue1:
parameter = startValue1
if parameter > endValue1:
parameter = endValue1
Span1 = endValue1 - startValue1
Span2 = endValue2 - startValue2
rate = float( parameter - startValue1 ) / Span1
value = startValue2 + ( rate * Span2 )
return value
#参照
ryusas/test_falloffCurveAttr.py
https://gist.github.com/ryusas/699ad3f5fa8469a00e8df4b3672aa89f
Maya Python Advent Calender 2020の4日目は、it_ksさんの記事です!!