エラーをキャッチする例文
いつも忘れるのでメモで残しておきます。
エラーを判定するための例文。
VBSに例えるとOn error resume nextに近いかな。
#xsi = Application try: xsi.NewScene("", False) except: print 'error'
コメント#を外すとちゃんとNewSceneされます。
選択した、頂点、ポリゴン、エッジが入っちゃっているクラスタを調査する
Twitterでふられたので、Pythonで作ってみました。
選択した頂点等、コンポーネントがちょっとでもかすっているクラスタを調査し、選択します。
名付けて、「出てこいクラスター」もしくは「表に出ろやクラスター」
内容は雑ですが、大体こんな感じかと・・・。
SIのコンポーネントを探したいときに階層のいちいち深いところまでいかないといけない典型的な例でした。
なんで横のつながりでサクッといかないんでしょうかねぇ・・・。
どっかの大きな組織のようですねぇ。w
それにしても、Pythonまじ便利。
import win32com.client from win32com.client import constants try: # Applicationを短縮 app = Application selist = [] oCmp = app.GetValue("SelectionList") clstype = '' # 選択したオブジェクト分だけ回す for oSel in oCmp: oObj = oSel.SubComponent.Parent3DObject # print oSel.SubComponent.Parent3DObject # 選択された頂点毎に調査 for oSubcmp in oSel.SubComponent.ComponentCollection: # print oSubcmp.index # 選択対象のタイプを絞る(ていうかサブコンポーネントとクラスタのタイプ名が違うのはなんで??) if str(oSubcmp) == 'Vertex': clstype = 'pnt' elif str(oSubcmp) == 'PolygonFace': clstype = 'poly' elif str(oSubcmp) == 'Edge': clstype = 'edge' # 選択した頂点がクラスタの中に存在しているか調査 for oCls in oObj.ActivePrimitive.Geometry.Clusters: # クラスタタイプ調査 if clstype == oCls.type: # リストに調査クラスタが入っていないか? if selist.count(str(oCls)) == 0: myElem = oCls.Elements a = 0 # print '-cluster elements ' + oCls.type while a < len(myElem): # print myElem(a) if oSubcmp.index == myElem(a): # print clstype + '==' + oCls.type print oCls selist.append(str(oCls)) break a = a + 1 # print '選択対象確認 ' + selist app.SelectObj(selist, "", "") except: print 'エラー!'
デュプリケイトシンメトリーフロムオブジェクトPythonソン
JunkiTheJunkieさんの「SIのシンメトリコピーってローカルが無いのか?」という呟きを元に、折角なのでPythonScriptの勉強をかねて作ってみました。
っていうかPython勉強用の備忘録ではじめたの忘れてたw
内容は対象複製したものをピックしたオブジェクトとの座標別の距離を測って反対側に持っていく・・・っていうだけですが、SIのPythonの癖が少し入っているので参考までに…。
import win32com.client from win32com.client import constants # Applicationを短縮 app = Application # XSIDialogをPythonで使える形に xsidial = win32com.client.Dispatch( "XSIDial.XSIDialog" ) res = xsidial.ComboEx( 'title', ["XY Plane (z=0)","XZ Plane (y=0)","YZ Plane (x=0)"], 2 ) # キャンセルだとresに-1が入るのでその際は終了 if res is not -1: oColl = app.GetValue("SelectionList") # DuplicateSymmetryの基点Planeの設定を決定 cp = [0,0,1] if res == 1: cp = [0,1,0] elif res == 2: cp = [1,0,0] # Pythonでは出力引数をサポートしていないのでタプルを利用して変数を組む(クリックされたボタン、修飾キー、ピックオブジェクト) # 対象基点にするオブジェクトをピックで選択させる oBtn,oMod,oPicked = app.PickObject( 'Pick CenterObject...', 'Pick CenterObject...' ) # 基点オブジェクトのGlobalのポジションを取得 ctrgpos = [ app.GetValue(oPicked.Kinematics.Global.Parameters("posx")), app.GetValue(oPicked.Kinematics.Global.Parameters("posy")), app.GetValue(oPicked.Kinematics.Global.Parameters("posz"))] # app.Logmessage( 'Picked : ' + str(oPicked) ) # app.Logmessage( 'Modify Key : ' + str(oMod) ) # 基点オブジェクトをピック時にCtrlを押していたら親共有モード pmod = "" if oMod == 2: pmod = True # 選択オブジェクトを繰り返す for oSel in oColl: # 複製オブジェクトのGlobalのポジションを取得 orggpos = [ app.GetValue(oSel.Kinematics.Global.Parameters("posx")), app.GetValue(oSel.Kinematics.Global.Parameters("posy")), app.GetValue(oSel.Kinematics.Global.Parameters("posz"))] # DuplicateSymmetryはそのまま使用 oDup = app.DuplicateSymmetry(oSel, "", pmod, cp[0], cp[1], cp[2], 0, "") app.Logmessage( 'Picked : ' + str(oDup) ) if cp[0] == 1: app.SetValue(str(oDup)+'.kine.global.posx',(ctrgpos[0] - (orggpos[0] - ctrgpos[0]))) elif cp[1] == 1: app.SetValue(str(oDup)+'.kine.global.posy',(ctrgpos[1] - (orggpos[1] - ctrgpos[1]))) elif cp[2] == 1: app.SetValue(str(oDup)+'.kine.global.posz',(ctrgpos[2] - (orggpos[2] - ctrgpos[2])))
・・とまぁ観てお分かりかとおもいますが、SIでのPythonはコマンドの出力引数をサポートしていないので、変わりにタプル変数を使うとか、XSIDialogを使うときはwin32com.clientをインポートしてDspatchするとかあたりがVBSやJAVAスクリプトとかと勝手が違うところかな??
Shatterもどき??
今日Twitterを通じてほろにがさんの記事を読んで、ふむふむ、前半はこういうことかな?
→http://www.dfx.co.jp/dftalk/?p=757
とSoftimage用のスクリプトで起こしてみました。
これを切り刻む分だけ繰り返せばいいのかな?
今回はVBSですが・・・w
Dim ret Dim oCol, oSel ' オブジェクトを選択 Set oCol = GetValue("SelectionList") for each oSel in oCol Logmessage "Cutting : " & oSel ' 選択オブジェクトのバウンディングボックス座標を取得 GetBBox oSel, FALSE, xmin, ymin, zmin, xmax, ymax, zmax ' 選択オブジェクトのXYZそれぞれの長さを計算 Dim xLen, yLen, zLen ret = Abs(xmax - xmin) if ret = 0 then ret = 0.1 xLen = ret ret = Abs(ymax - ymin) if ret = 0 then ret = 0.1 yLen = ret ret = Abs(zmax - zmin) if ret = 0 then ret = 0.1 zLen = ret Logmessage "BBoox : " & xmin&", "&ymin&", "&zmin&", "&xmax&", "&ymax&", "&zmax ' スライス用のGridを生成 Dim oSliceGrid Set oSliceGrid = CreatePrim( "Grid", "MeshSurface" ) GetBBox oSliceGrid, FALSE, sxmin, symin, szmin, sxmax, symax, szmax ' スライス用のGridのサイズを計算して、選択オブジェクトのサイズより大きくなるようにする(2倍ぐらい?) Dim sXlen, sYlen, sZlen, sclX, sclY, sclZ ret = Abs(sxmax - sxmin) if ret = 0 then ret = xLen sXlen = ret ret = Abs(symax - symin) if ret = 0 then ret = yLen sYlen = ret ret = Abs(szmax - szmin) if ret = 0 then ret = zLen sZlen = ret sclX = (xLen / sXlen) * 2 sclY = (yLen / sYlen) * 2 sclZ = (zLen / sZlen) * 2 Scale oSliceGrid ,sclX,sclY,sclZ, siRelative, siLocal, siObj, siXYZ, , , , , , , , 0 ' ブーリアンを安定化するためにGridを三角形化 ApplyTopoOp "TriangulatePolygons", oSliceGrid, siUnspecified, siPersistentOperation ' Gridの頂点をランダマイズで波打たせ〜 Dim oP Set oP = ApplyOp("Randomize", oSliceGrid, 3, siPersistentOperation, , 0) Logmessage oP SetValue oP & ".amply", 0.01 SetValue oP & ".amply", 1 SetValue oP & ".amplz", 1 ' Gridを使って選択をブーリアン、法線を反転させ、ブーリアン ApplyTopoOp "BooleanDifference", oSel & ";" & oSliceGrid, 3, siPersistentOperation Set oDup = Duplicate( oSel, , 2, 1, 1, 0, 0, 1, 0, 1, , , , , , , , , , , 0 ) FreezeModeling oDup ApplyTopoOp "Inverse", oSliceGrid, 3, siPersistentOperation Set oDup = Duplicate( oSel, , 2, 1, 1, 0, 0, 1, 0, 1, , , , , , , , , , , 0 ) FreezeModeling oDup next
IllustratorでVBS2
TextFramesの動作がおかしいって今まで悩んでいたのがバカみたいです・・・
こっちの方が確実で、効果的でした。orz...
Set appRef = CreateObject("Illustrator.Application.4") For Each pItem in appRef.ActiveDocument.PageItems If pItem.PageItemType = 10 Then pItem.CreateOutline End If Next
ActiveDocument.PageItemsプロパティを使うと、ドキュメント内のオブジェクトを階層関係なしにごっそり取得できます。
その中からPageItemTypeで検査をかけて、文字オブジェクトを判別し、アウトライン化すればよかった…。
※それにしても、ForでItemsのコレクションを回した時に、ループ処理の途中で個数の整合性が合わなくなる?(もしくは入れ替わる?)
結果処理が不明のエラーでとまってしまうのをうまく回避するコツってあるのかナァ・・・
IllustratorでVBS
しばらく家ではIllustratorのVBScriptを書いているのでPythonは一旦休止。
といっても1ヶ月くらいで再開するけど・・・w
とりあえず長い間なぞの動作をしていたTextFramesからTextFrameを取得すると、取得できない(処理から飛ばされる)TextFrameが存在するバグの回避策が分かりました。
:例
For Each oTxt in oLayer.TextFrames If oTxt.Contents <> "" Then flag = true for each t in colTxtFrames if t.Contents = oTxt.Contents then flag = false end if next if flag then Redim Preserve colTxtFrames(i) Set colTxtFrames(i) = oTxt i = i + 1 end if End If Next
といった感じで配列に一度テキストフレームを全て入れてから(内容が同じのを引っ張ってくることがあるので、内容が同じだったらいらないってする)、外でその配列をもう一回Forで回して例えばOutlineにするとか・・・・。