Maya のシミュレート 1

Maya のしくみ

Mayaのシーンは、DGとDAGによって作られています。
そのうちのDGと同じ原理の仕組みを作ってみましょう。
DGでは、あるノードのアトリビュート値が変更されると、 そのアトリビュートにコネクトされたアトリビュートの値が、 自動的に同じ値に変更される必要があります。 この仕組みを作るためには、デザインパターンの一種であるオブザーバ(Observer)パターンを応用します。

オブザーバ・パターン

あるオブジェクトの状態が変化したときに、他のオブジェクトにそれを知らせる仕組みです。
オブザーバ・パターンでは、そのために状態が変化したことを知らせる専用のメソッドを定義します。
以下の例では、nmaya1.pyの_notify_observersメソッドなどがコネクトしたノードに状態が変化したことを知らせるメソッドになっています。

オブザーバ・パターンの例

以下のスクリプトは、オブザーバ・パターンの原理を利用して、 MayaのDGと似た動作をシミュレートしたものです。
なるべく、スクリプトをシンプルにするために、ノードのアトリビュートは一つだけとします。 また、アトリビュートにコネクトできるアトリビュートも一つだけです。
このスクリプトを実行するとプロンプトが表示されるので、 ノードを作成し、メソッドを実行してゆきます。

作成できるノードの種類は以下の1種類だけです。

Node(attr)
attrをアトリビュート値としてインスタンスを作成します。

ノードで使用できるメソッドの種類は以下の通りです。

getAttr()
アトリビュートの値を返します。
setAttr(val)
アトリビュートに値valを設定します。
connectAttr(node)
他のnodeのアトリビュートと、自分のアトリビュートをコネクトします。
自分のアトリビュートが変化すると、nodeのアトリビュート値も同じ値になります。

その他、以下のメソッドを使用します。

sys.exit(0)
コマンドの実行を終了します。
  1. 以下のPythonスクリプトを nmaya1.py というファイル名で保存します。
    import sys
    
    
    class Node(object):
        def __init__(self, attr=0):
            self.attr = attr
            self.observer = None
    
        def _update(self, node):
            self.setAttr(node.getAttr())
    
        def _notify_observers(self):
            if self.observer:
                self.observer._update(self)
    
        def connectAttr(self, node):
            self.observer = node
            self._notify_observers()
    
        def getAttr(self):
            return self.attr
    
        def setAttr(self, val):
            self.attr = val
            self._notify_observers()
    
    
    def quit():
        sys.exit(0)
    
    
    while(1):
        s = raw_input('command: ')
        exec(s)
    
  2. シェル上で、以下のコマンドを実行します。
    % python nmaya1.py
  3. プロンプト(command:)が表示されたら、以下のPython関数を実行します。
    command: n1 = Node(1)
    command: n2 = Node(2)
    これで、n1, n2 というノードが作成されました。
  4. 各ノードのアトリビュート値を調べてみます。
    command: print n1.getAttr()
    1
    command: print n2.getAttr()
    2
    最初に設定したアトリビュート値(1 と 2)が表示されます。
  5. n1ノードをn2ノードにコネクトしてみます。
    command: n1.connectAttr(n2)
  6. n2ノードのアトリビュート値を調べてみます。
    command: print n2.getAttr()
    1
    n2ノードのアトリビュート値が、n1ノードのアトリビュート値と同じになっているのがわかります。
  7. n1ノードのアトリビュート値を変更してみます。
    command: n1.setAttr(3)
  8. n2ノードのアトリビュート値を調べてみます。
    command: print n2.getAttr()
    3
    n2ノードのアトリビュート値が自動的に変更されているのがわかります。
  9. スクリプトを終了します。
    command: quit()

スクリプトの解説

import sys
whileループ内で、Python式の入力を終了するためにインポートします。
nmaya1.py内では使用していません。
class Node(object):
ノードクラスを定義します。
def __init__(self, attr=0):
ノードの初期化メソッドです。
引数attr はアトリビュートの初期値を表します。
attr が与えられない場合は 0 になります。
self.attr = attr
インスタンス変数 self.attr に初期値 attr を代入します。
self.observer = None
最初は、オブザーバ(アトリビュートを監視するノード)は無し(None)にしておきます。
def _update(self, node):
自分のアトリビュートをオブザーバによって更新するメソッドです。
self.setAttr(node.getAttr())
オブザーバ(node)からアトリビュートの値を取り出して(getAttr())、 自分のアトリビュートに設定(setAttr())します。
def _notify_observers(self):
オブザーバによって、アトリビュートを更新するメソッドです。
if self.observer:
オブザーバが存在するかどうか調べます。
self.observer._update(self)
オブザーバが存在すれば、自分自身の_updateメソッドを実行します。
def connectAttr(self, node):
オブザーバを登録するメソッドです。
self.observer = node
インスタンス変数 self.observer にオブザーバノードを代入します。
self._notify_observers()
このクラスの_notify_observersメソッドを実行します。
def getAttr(self):
このクラスのアトリビュート値を得るメソッドです。
return self.attr
アトリビュート値を返します。
def setAttr(self, val):
このクラスのアトリビュートに値を設定するメソッドです。
self.attr = val
インスタンス変数self.attrに値(val)を代入します。
self._notify_observers()
_notify_observersメソッドを実行して、オブザーバのアトリビュートも変更します。
def quit():
プログラムを終了するための関数です。
sys.exit(0)
sysモジュールのexit()関数によってプログラムを終了します。
while(1):
コマンドを入力するために、永久ループを実行します。
s = raw_input('command: ')
プロンプト(command:)を表示し、標準入力から入力した文字列をsに代入します。
exec(s)
sの文字列をPythonの式として実行します。

参考


Prev | Prev
Home | Contents
Mail