my funeral week

少しでも日々の生活に変化を。

MayaScripts_PrimitiveRigGenerator:リグ用のノード生成補助ツール

こんにちは。

今回もMaya用スクリプトを紹介します。

PrimitiveRigGenerator

今回は非常にシンプルなリグノードの生成補助ツールを制作しました。
とは言っても、基本的に一時的な外部ノードの生成を行うようなスクリプト用のモジュールです。

このスクリプトをご自身のスクリプトにインポートすることで、簡易的ではありますがNurbusCurveで構成されたオブジェクトを生成できます。

シンプルが故にあらゆるニーズに答えられるものではありませんが、ご了承ください。

www.dropbox.com

クリエイティブ・コモンズ・ライセンス


インストール

まずは上記リンクからフォルダをDLして、以下の場所に保存してください。

C:\Users\"ユーザー名"\Documents\maya\scripts


以下のコードでインポートできます。

import PrimitiveRigGenerator


生成できるノードについては、「shapes」という名前のフォルダ内にあるものに限られます。
全てNurbusCurveノードのみで構成された、「ma」ファイルになります。

各ファイルの中身は・・・

  • box
    • シンプルな立方体
      f:id:garysfirearms108:20200209112009j:plain:w86
  • compass
    • 4方向に伸びる矢印平面
      f:id:garysfirearms108:20200209112410j:plain:w86
  • cross
    • 立体的な十字
      f:id:garysfirearms108:20200209112426j:plain:w86
  • diamond
    • ダイアモンド型の立体
      f:id:garysfirearms108:20200209112444j:plain:w86
  • pyramid
  • sphere
    • 球状の立体
      f:id:garysfirearms108:20200209112522j:plain:w86
  • vector
    • 矢印
      f:id:garysfirearms108:20200209112539j:plain:w86

という感じです。
ファイルにはありませんがLocatorも生成できます。


使い方

このスクリプト自体にUIは含まれていません。
実行するには、インポートしたスクリプト内で以下のようなコードが必要です。

PrimitiveRigGenerator.getShape (
    name,
    newName = "Primitive",
    scaleValue = (1,1,1),
    colorValue = 0,
    freeze = True
    )

各引数に関して

  • name
    • shapeフォルダ内のファイル名(.maは省略)
    • 以下の値のどれかを利用してください。
  • newName
    • 生成時の名前
  • scaleValue
    • スケール値(X,Y,Z)
  • colorValue
  • freeze
    • 生成時のスケールをフリーズするかどうか
    • ロケーターを選んだ場合はフリーズするとスケール値がリセットされます(Mayaの仕様)


具体的な使用例

前回の記事にて、
トランスフォームのRotateOrderアトリビュートを変更するスクリプトの紹介をしましたが、そのスクリプトのオプションとして、外部ノードの生成を行う機能がありました。

chototoilet108.hatenablog.com

記事内のコードで言うと以下の部分がそれにあたります。

self.dst = pm.spaceLocator(n = target.name() + "_Extracted")


外部ノードの生成部分はMayaのLocator生成関数を使っています。
PrimitiveRigGeneratorをこのスクリプト内にインポートした上で、該当箇所を以下のように置き換えると、Locatorの代わりに「pyramid」が生成されます。

self.dst = PrimitiveRigGenerator.getShape("pyramid",target.name() + "_Extracted")


おまけ

一応、動作確認用に作成したGUIのコードを掲載しておきます。

# -*- coding:utf-8 -*-

import pymel.core as pm
import PrimitiveRigGenerator as rigGen

def deleteExistUI (name):
    if pm.window(name, q = True, ex = True):
        pm.deleteUI(name)

def buildUI ():
    windowName = "PrimitiveRigGenerator"
    windowSize = [200, 250]
    
    rigGen.main() # PrimitiveRigGeneratorの初期化
    
    deleteExistUI(windowName)
    
    with pm.window(windowName, mnb = False, mxb = False) as w:
        w.setWidthHeight(windowSize)
        
        with pm.columnLayout(adj = True, rs = 5):
            pm.text(l = "Select a Shape", bgc = [0.9,0.5,0.3])
            
        with pm.columnLayout(adj = True, rs = 5, co = ["both", 5]):
            pm.separator(st = "in", h = 2)
            shapeMenu = pm.optionMenu(l = "Shape")
            shapeMenu.addItems(rigGen.getShapeFileNames())
            pm.separator(st = "in", h = 2)
            
            with pm.rowLayout(nc = 2):
                pm.text(l = "Name")
                nameField = pm.textField(tx = "NewRig", w = 170)
            
            pm.separator(st = "in", h = 2)
            
            colorField = pm.colorIndexSliderGrp(min = 0,max = 31)
            
            pm.separator(st = "in", h = 2)
            
            with pm.rowLayout(nc = 2):
                pm.text(l = "X", w = 30)
                xField = pm.floatField(v = 1.0, w = 155)
            
            with pm.rowLayout(nc = 2):
                pm.text(l = "Y", w = 30)
                yField = pm.floatField(v = 1.0, w = 155)
                
            with pm.rowLayout(nc = 2):
                pm.text(l = "Z", w = 30)
                zField = pm.floatField(v = 1.0, w = 155)
            
            pm.separator(st = "in", h = 2)
            
            with pm.rowLayout(nc = 2):
                
                generateCommand = lambda *arg:rigGen.getShape(
                    shapeMenu.getValue(),
                    nameField.getText(),
                    [xField.getValue(), yField.getValue(), zField.getValue()],
                    colorField.getValue() - 1 if colorField.getValue() != 0 else 0
                )
                
                pm.button(l = "Generate", c = generateCommand, w = 95)
                pm.button(l = "Close", c = lambda *arg:deleteExistUI(windowName), w = 95)


上記の「buildUI()」を実行すると以下の画像のようなWindowが表示されます。

f:id:garysfirearms108:20200209112638j:plain

あくまで動作確認用のものなので、ユーザービリティをガン無視したものですが、
こちらのソースコードを見れば、より使い方も理解しやすいかもしれません。


余談

前回のRotateOrderSwitcherをはじめとして、自分のよく利用するスクリプトにはアニメーションを制御するノードをリグの外部に生成するという機能を付けることが多いです。
その際に、一時的な利用とは言え、曲がりなりにもリグノードなのだから「Locator」だけで済ますのはなんだか使い勝手が悪いな~っと感じることが増えてきたので制作しました。

なので、はっきり言って自分用のものです。

この辺りはMayaもかつてのXSIを見習ってデフォルトでリグ制作に使えるような、プリミティブ形状のノード生成機能を設けてくれればいいんですけどね~。

それじゃまた。