Maya はノードのアトリビュート同士をコネクトすることによってシーンを構成してゆく。
つまり、ノード間をアトリビュートによってコネクトするしくみがわかれば Maya と同じシステムを作ることができる。
あるノードのアトリビュートが変化した時、そのアトリビュートがコネクトされている他のノードのアトリビュートが同期して変化すれば良い。
これを実現するにはデザインパターンにおける Observer パターンを応用する。
Maya の内部構造を真似たシンプルな C++ プログラムの例である。
わかりやすくするためにノードは一種類(NodeA)、アトリビュートは一つだけ(int)にしている。
#define MAX_OBSERVER 32
class AbstructNode
{
public:
AbstructNode(){}
};
class Observer
{
public:
Observer(){}
virtual void update(AbstructNode *) = 0;
};
class Node : public AbstructNode
{
private:
int current;
Observer *unodes[MAX_OBSERVER];
public:
Node()
{
current = 0;
}
void connectAttr(Observer *);
void notify(void);
virtual int getAttr(void) = 0;
virtual void setAttr(int) = 0;
};
void Node::notify(void)
{
for(int i = 0; i < current; i++)
{
Observer *o = unodes[i];
o->update(this);
}
}
void Node::connectAttr(Observer *obs)
{
if(current < MAX_OBSERVER)
{
unodes[current] = obs;
current++;
}
}
class NodeA :public Node, Observer
{
private:
int attr;
public:
NodeA()
{
attr = 0;
}
void update(AbstructNode *);
int getAttr(void);
void setAttr(int);
};
void NodeA::update(AbstructNode *node)
{
Node *n = (Node *)node;
setAttr(n->getAttr());
}
int NodeA::getAttr(void)
{
return attr;
}
void NodeA::setAttr(int val)
{
attr = val;
notify();
}
#include <stdio.h>
#include "nmaya.h"
void main()
{
NodeA n1, n2, n3;
printf("( n1 %d ) ", n1.getAttr());
printf("( n2 %d ) ", n2.getAttr());
printf("( n3 %d )\n", n3.getAttr());
n1.connectAttr((Observer *)(&n2)); // ノード n1のアトリビュートを n2 にコネクト
n2.connectAttr((Observer *)(&n3)); // ノード n2のアトリビュートを n3 にコネクト
printf("( n1 %d ) -> ", n1.getAttr());
printf("( n2 %d ) -> ", n2.getAttr());
printf("( n3 %d )\n", n3.getAttr());
n1.setAttr(2); // ノード n1のアトリビュートを 2 に変更
printf("( n1 %d ) -> ", n1.getAttr());
printf("( n2 %d ) -> ", n2.getAttr());
printf("( n3 %d )\n", n3.getAttr());
}
% cc test1.c++ % ./a.out ( n1 0 ) ( n2 0 ) ( n3 0 ) ← ノード n1, n2, n3 のアトリビュートの初期値は 0 ( n1 0 ) -> ( n2 0 ) -> ( n3 0 ) ← n1 から n2、 n2 から n3 へコネクトされた状態 ( n1 2 ) -> ( n2 2 ) -> ( n3 2 ) ← n1 のアトリビュートを変更すると n2, n3 も変更される