2008/11/28

XSI 7.01 Released.

やー。出ましたね。
少しは、プロダクションで使えるようになったでしょうか。

Fixed Bugs Listを見てみると恐ろしい量です・・・。

UDEV00248322 - Incidence Node "Light List" is broken
IncidenceのLight Listは直ったみたい?

UDEV00248548 - Loading the Vector to Color node from the top menu does not work
Vector to Colorが見えるようになったのかな?

UDEV00247262 - Hidden Line Display and material with Transparency can cause XSI to crash
うひひっ。恐ろしや。

でも、7.02が出るまで我慢だなぁ。

2008/11/26

Sukio Sukio Sukio Python - V

みなさまこんにちは。5回目になりました。

さて、今回は、OM、オブジェクトモデルの探し方です。
せっかくオブジェクト指向の言語Pythonを使用していますので、XSIも合わせて使ってみましょう。

その前に、オブジェクト指向とはなんでしょうか?
ワタクシも上手く伝え切れませんが、XSIをモデルに考えると、Explorerをイメージすると分かりやすいと思います。
Nullには、Primitive、Kinematics、Visibility、Display
とプロパティの引き出しがあり、そのそれぞれにパラメータを持ち、値を変えることが出来ます。
Pythonの中にもこういった階層構造があり、stringでさえオブジェクトモデルでありその下には

'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find',

'index','isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join',

'ljust','lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition',

'rsplit','rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate',

'upper','zfill'


と本当にたくさんの便利なメソッドが用意されています。
これらを使いこなしてこそ、Pythonを使う意味があるというもの。
OMを使わなければ、Pythonでなくても良いのです。
このように、XSIのメソッドを知るということと、Pythonのメソッドを知るということは別のことであり、両方学ばなければ十分に力が発揮されないことが理解出来ることでしょう。

では、本題に戻りましょう。

まず、テキトーに物を作って、階層構造を作って、ランダマイズを掛け、値をいじって、移動して、レンダリングをオフ、グループを作成して、というCMのログを見てみます。


Application.NewScene("", "")
Application.GetPrim("Null", "", "", "")
Application.CreatePrim("Sphere", "MeshSurface", "", "")
Application.CopyPaste("sphere", "", "null", 1)
Application.ApplyOp("Randomize", "sphere", 3, "siPersistentOperation", "", 0)
Application.SetValue("sphere.polymsh.randomizeop.amplx", 2, "")
Application.SetValue("sphere.polymsh.randomizeop.amply", 2, "")
Application.SetValue("sphere.polymsh.randomizeop.amplz", 2, "")
Application.Translate("", 1, 0, 0, "siAbsolute", "siPivot", "siObj", "siX", "", "", "", "", "","", "", "", "", 0, "")
Application.Translate("", 0, 1, 0, "siAbsolute", "siPivot", "siObj", "siY", "", "", "", "", "","", "", "", "", 0, "")
Application.SetValue("sphere.visibility.rendvis", 0, "")
Application.CreateGroup("", "", "")


こんな感じです。
多くのスクリプトは

Application.SetValue(oObj+".polymsh.randomizeop.amplx", 2, "")

などして、汎用性を高めているに留まっています。
これを実行しても、立派にスクリプトと言えるでしょう。
ですが、ちょっと見にくい感じです。
ですので、もう一段階レベルを上げる事を考えて見ます。
このCMをほとんどOMに変えてみます。


app=Application
app.NewScene()
oRoot = app.ActiveSceneRoot
oNull = oRoot.AddNull()
oObj = oNull.AddGeometry('Sphere','MeshSurface')
oOp = XSIFactory.CreateObjectFromPreset( "Randomize", "Operators" )
oOp.connect(oObj)
oOp.amplx.Value = 2
oOp.amply.Value = 2
oOp.amplz.Value = 2
oObj.posx.Value = 1
oObj.posy.Value = 1
oObj.rendvis.Value = False
oRoot.AddGroup(oObj)


物凄くスッキリしました。
そして、実行すると一瞬で返ってきます。
CMは、NewScene()のみです。

app=Application

まず、Applicationはとても長いので、appと短い変数にしてあげます。
xsiとしている人も居ます。自分が分かればOKです。

さて、Scene_Rootは、何を実行すれば取得出来るでしょうか?
ApplicationのSDKマニュアルを見てみましょう。
このオブジェクトには、これだけのメソッド、プロパティが用意されています。

メソッド
ActivateWorkgroup  AddCommand  AddWorkgroup  Advise  
ClassName  CreateAddon  CreateCommand  CreateProject  
ExecuteScript  ExecuteScriptCode  ExecuteScriptCommand  GetCommandByScriptingName  
InstallAddon  IsClassOf  IsEqualTo  LoadPlugin  
LogMessage  RemoveCommand  RemoveWorkgroup  RescanWorkgroups  
Unadvise  UnInstallAddon  UnloadPlugin  UpdatePlugins  
Version           

プロパティ
ActiveProject  ActiveSceneRoot  ActiveToolName  Application  
Categories  Commands  Desktop  Devices  
Dictionary  EventInfos  Filters  FullName  
Help  InstallationPath  Interactive  License  
Name  NestedObjects  Origin  OriginPath  
Parent  Platform  Plugins  Preferences  
Selection  StatusBar  Type  Workgroups  


たくさんありますね。

Application.Selection

としてあげれば、選択されたものが取得出来ます。
肝心のScene_Rootですが、プロパティの2つ目、ActiveSceneRootがそれに当たります。

oRoot = app.ActiveSceneRoot

Scene_Rootに行う処理は、2回ありますので、取り合えず変数oRootに入れておきます。
次に、ActiveSceneRootにNullを追加したいので、ActiveSceneRootのページに行き戻り値Modelというリンクを辿ってみましょう。
これまた物凄くたくさんのメソッド群ですね。
ここからNullが出そうなものはAddNullというメソッドを利用しようと思います。

oNull = oRoot.AddNull()

またまたリンクを辿るとAddNullには、ひとつ引数を与えられるみたいです。
Stringを与えれば、その名前で追加します。

AddNull('null_generate_by_script')

などですね。今回は、省略します。
ついでに出したNullは、oNullという変数に入れてあげます。

oObj = oNull.AddGeometry('Sphere','MeshSurface')

nullの子供にSphereを加えたいので、AddGeometry()を使います。第一引数は、プリセット。第二引数は、メッシュなのかナーブスかです。これもついでにoObjとしておきます。

oOp = XSIFactory.CreateObjectFromPreset( "Randomize", "Operators" )
oOp.connect(oObj)

オペレータは、ApplyOp()を主に使いますが、今回は、完全OMにしてみました。
Randomizeオペレータを一度シーンに呼び出し、適用させたいオブジェクト(この場合oObjです)にコネクトします。
ですが、ApplyOp()はとても便利ですので、そのまま使ったほうが良いときがほとんどです。
この場合は

app.ApplyOp("Randomize",oObj)

でOKでしょう。
ただし、返り値が問題です。
コマンド、ApplyOp()は、配列のXSICollectionで返ってきてしまいます。
オペレータオブジェクトの外側にXSICollectionという殻が付いている状態です。
(OperatorObject)←こんな感じ。

ですので、殻の中身を食べたいのでこの様に大抵(0)を付けてあげて、0番目の配列を選んであげます。
これにより、オペレータオブジェクトを直に変数に入れています。

oOp = app.ApplyOp("Randomize",oObj)(0)

こんな感じですね。oOpには、ランダマイズオペレータが入っています。
それでは、ランダマイズオペレータのDisplacementをXYZ全て2にします。
Operatorで検索をかけ、Operatorページに行ってみましょう。
おや?アンプリチュードの値を変えられそうなメソッド、プロパティは、無さそうです。
そうなのです。パラメータの値は、いちいちマニュアルには書いて居ないのです。
パラメータの名前を知るには、オペレータを選択して、Inspectし、Markingします。
Xをクリックしてみましょう。
するとログには、こう出ます。

Application.SetMarking("amplx")

DisplacementのXの値は、"amplx"という名前なのが分かりました。
ですので、この値をセットするには

oOp.amplx.Value = 2
oOp.amply.Value = 2
oOp.amplz.Value = 2

このように書きます。
本来ですと

oOp.Parameters("amplx").Value = 2

と書きます。
これはショートカットがききますので、ダイレクトにも書くことが出来ます。
ショートカットで検索すれば、いろいろ出てきますので、参考にしましょう。
出来ないものと出来るものがあるので、注意です。
出来なかったら、Parametersを使えばOKです。

oObj.posx.Value = 1
oObj.posy.Value = 1

Kinematicsも同様の探し方です。
ショートカットを使いましょう。
本来の書き方は

oObj.Kinematics.Local.posx.Value = 1

です。
さて、次は、VisibilityのRenderViewのチェックをオフです。
これもショートカットが存在します。
良く使うものには大抵ついています。

oObj.rendvis.Value = False

これでOKです。

oObj.Properties("Visibility").Parameters("rendvis").Value

どちらでもといった感じでしょうか。
ちなみに、Explorerで、四角いノードは、プロパティを示しています。
名前が分かれば、Propertiesで取得出来ます。

最後に、グループです。
グループは、モデルに付くものです。ですので、Modelのマニュアルを覗いて見ると
ありました、AddGroup()。
これを使用しましょう。

oRoot.AddGroup(oObj)

第一引数は、メンバーを入れます。
ここに入るのは、OMでないと受け付けてくれません。
OMで処理するには、OMを使用しなければなりません。

Application.CreateGroup(sName,oObj)

逆に、CMは、StringでもOMでも入れればGroupに入れてくれるようです。
融通はこちらのほうが上でしょうか。

現存のグループの名前が分かっている場合の取得方法は

Application.ActiveSceneRoot.Groups("ABC")

とすれば、ABCという名前のグループが取得出来ます。
こちらも便利でしょ?

という感じです。
未だPythonのOMには、たどり着きませんでしたが、いかがでしたか?
今回は、Pythonの部分に全く触れていないので、この説明は、vbでもjsでも同じことが言えます。

題材をちょっと間違えたかもなぁ・・・ω
ま、いっか。

OMには、いろんなメリットがあり、必要なオブジェクトに瞬時にアクセスすることが出来ます。
そして、処理スピードには、天と地の差が開く事になります。
覚えるのは結構大変ですが、SDKマニュアルとお友達になれば、いつでも助けてくれることでしょう。

というわけで、次回は、Pythonの使い方に注目してみましょう。
String、List辺りをやってみようと思います。
ファイル操作もやってみてもいいかも知れません。

それでは、またお会い出来るのを心待ちにしてます。

おたのしみに。

2008/11/10

Softimage : Sukio Sukio Sukio Python - IV : UIの基本構造

今回で、4回目になりました。
スクリプティングは、毎回同じことをやらせるのにとても都合のいいものです。
寝ている間に、作業を終わらせることだって可能なのです。
物量が無ければ、ほとんど意味の無いものですけど。

さて、今回は、カスタムプロパティを使い、なんらかの動作をさせるボタンを作成してみましょう。

単純に、ボタンを押したら選択されているもののposXをパラメータの値に移動するというものを作ってみます。


from win32com.client import constants as c

LogicCode = """
def PosX_OnClicked():
    app = Application
    log = app.LogMessage
    fNmb = PPG.Number.Value
    app.Selection(0).Posx.Value = fNmb
    log(fNmb)
"""

app = Application
log = app.LogMessage

oPSet = app.ActiveSceneRoot.AddProperty(
    "CustomProperty",
    False,
    "ButtonTEST" )

oPSet.AddParameter2(
    "number",
    c.siDouble,
    0.0,
    -20.0, 20.0,
    -20.0, 20.0,
    c.siClassifUnknown,
    c.siPersistable | c.siAnimatable )

oLayout = oPSet.PPGLayout

oLayout.AddButton( "PosX" )
oLayout.AddItem( "Number" )

oLayout.Language = "Python"
oLayout.Logic = LogicCode

app.InspectObj( oPSet, "", "", c.siLock )


いささか難しいコードになってしまいますが、一番シンプルな形ではないでしょうか。
CMは、InspectObjのみとなってしまいますが、解説をいたします。

XSIでのUIのダイアログの事をPPG(Property Page)と呼びます。
PPGを作るには、3つの段階が必要になります。

1. 内部的に処理するパラメータを定義する。(AddParameter)
2. PPG内のレイアウトにどのような形で変数を表示させるか。(AddItem)
3. ボタン、チェックボックス、ドロップダウンボックス、などをユーザーが押したり値をいじったら何を実行するか。(Logic)

まず、必要なパラメータを準備しましょう。
AddPropertyで、カスタムプロパティを作成します。

oPSet = app.ActiveSceneRoot.AddProperty( "CustomProperty", False, "ButtonTEST" )

ActiveSceneRootは、XSIの"Scene_Root"モデルを意味します。
そこにプロパティ"ButtonTEST"を付けなさいという命令文です。
イコールで繋ぐと、oPSetには、カスタムプロパティが入ります。

次に、選択したもののposXを入れたいのですから、浮動小数点のタイプを用いたほうがいいでしょう。
AddParameter2で、変数を作成します。

oPSet.AddParameter2("number",c.siDouble,0.0,-20.0, 20.0,-20.0,20.0,c.siClassifUnknown,c.siPersistable | c.siAnimatable )

この変数名をnumberということにします。
第2引数は、タイプですから、c.siDoubleという浮動小数点の定数を入れます。
あとは、表示するバーのデフォルトの値、最大最小値、内部的な制限の最大最小値、パラメータの分類(多くはデフォルトでOKです)
c.siPersistableは、値を保存可能に、c.siAnimatableはこのパラメータ自体をアニメーション可能にします。
物凄くたくさんのオプションが存在するので、マニュアルを見て、いろいろ試してみましょう。

次に、レイアウトを決めます。
oLayout = oPSet.PPGLayout

カスタムプロパティには、PPGLayoutというメソッドが存在します。
コレを用いて、レイアウトにアクセスします。
レイアウトに表示させたいものは、Numberというパラメータバーと実行するボタンです。

oLayout.AddButton( "PosX" )
oLayout.AddItem( "Number" )

ボタンを作成するときは、AddParameter2を用いなくても大丈夫。
ボタンにパラメータは必要ありません。
ボタンの下に、numberというパラメーターバーを表示させます。

ここまで、実行して、出来たプロパティをつつけば、レイアウト通り出来ているはずです。
ただし、ボタンを押しても何も動きません。
動作させるには、Logicメソッドを用いて、PPGに仕組みを覚えさせなければいけません。
この形で仕組みを書くには、LogicコードをStringで渡してあげなくてはならないのです。

Stringを使う際、"(ダブルクォーテーション)または、'(シングルクォーテーション)でくくった形になります。
しかし、Pythonでは、インデントや改行などがあり、通常一行で書くにはとても辛い所です。
ですが、'''を使う事によって、書いた文面を見た目通りに変数に入れることが出来ます。


LogicCode = """
def PosX_OnClicked():
    app = Application
    log = app.LogMessage
    fNmb = PPG.Number.Value
    app.Selection(0).Posx.Value = fNmb
    log(fNmb)
"""


LogicCode変数は、'''から'''までというニュアンスです。この中の

fNmb = PPG.Number.Value

という部分。これは、PPGのNumberというパラメータの値を参照します。
fNmbという変数に入れています。(自分だけ分かればいいので、float Numberの略です)
Selection(0)は、一番初めに選択したものになります。
ちなみに、Selection(1)は、二番目に選択したものが入ります。

app.Selection(0).Posx.Value = fNmb

ここで、ポジションXの値をfNmbから受け取っています。
フルで書くと

Application.Selection(0).Kinematics.Local.Posx.Value = fNmb

となりますが、キネマティクスのローカルは、ショートカットがききます。

最後のCM

app.InspectObj( oPSet, '', '', c.siLock )

これは、カスタムプロパティを左クリックでつついたように表示するってコマンドです。
c.siLockは、ページをロックします。
他のオブジェクトをInspectしても表示を切り替えないようにするためです。

以上、PPGの作り方の解説でした。
少々分からないことだらけでしょうが、一個一個解析していけば、素晴らしいUIが完成すること間違いなしです。

ちなみに、この書き方の弱点は、保存して、次に開いたときにレイアウトが保存出来ないってところです。
今回の、ボタンとパラメータバーだけでは大丈夫ですが、コンボボックスやら、チェックボックス、FCurveエディター、などなど、豪華に作ったはいいが、消えてしまうのね~というのが開発者として、一回は通る道になっております。
それを回避するには、カスタムプロパティ自体をプラグインとして登録してあげるしかありません。
これは、マニュアルや他の人が作ったやり方を参照したほうが、覚えるのは早いでしょう。
幸い、CustomPropertyWizardという恐ろしく便利なプリセット作成ツールがあるので、それを使ってくださいね。

次回は、OMを使って、パラメータにアクセスする方法の見つけ方でもやりましょうか。

ではでは、ゴキゲンヨウ!

Perforce: 複数のワークスペースを更新するバッチ

batを叩けば全部更新。 @echo off set P4PORT=x.x.x.x:xxxx set P4USER=user set P4PASSWD=password echo %P4PORT% echo %P4USER% echo %P4PASSWD% echo %P4PAS...