こちらの続きです。
NativeObjectとProxyの理解とモロモロ4 - C#ATIA
ここまで、スクリプトを実行すると中心座標が表示されましたが、恐らくそのような
スクリプトは作る機会が少ないと思います。
(テストやデモの場合は、使うかも知れませんが)
実際の場面であれば、スクリプトユーザーに要素を選択させ処理を行うのが
自然かな?と思っています。(今回であれば円を選択させる)
Fusion360の場合は大きく分けて2種類有りますが、UserInterfaceオブジェクトの
selectEntityメソッドがお手軽です。
Fusion 360 Help
ちょっと話がそれるのですが、selectEntityメソッドはESCキーを押すことで
選択処理を中止してくれるのですが、悪いことに例外を吐き出します。
(要はエラーでスクリプトが停止します)
以前、APIフォーラムにも記載しました。
Re: Bug? UserInterface.selectEntity should return None but fails - Autodesk Community
当時、てっきり周知の事実だと思っていたんですけどね。
で、未だに直ってません。("そのような仕様だ" で突き通すのでしょう)
話を戻しますが、ユーザーに円を選択をさせて、今までの知識を含めモロモロ情報を
表示させる様に変更してみました。
# Fusion360API Python script # sample4 import adsk.core, adsk.fusion, traceback def run(context): ui = None try: # おまじない app :adsk.core.Application = adsk.core.Application.get() ui :adsk.core.UserInterface = app.userInterface des :adsk.fusion.Design = app.activeDocument.design # ルートコンポーネント root :adsk.fusion.Component = des.rootComponent # ユーザーによる選択 msg :str = 'スケッチの円を選択して下さい / ESC - キャンセル' selFiltter :str = 'SketchCircles' sel :adsk.core.Selection = selectEnt(msg ,selFiltter) # ESCキーを押されたら終了 if not sel: return # 選択されたスケッチ円 circle :adsk.fusion.SketchCircle = sel.entity # SketchCircleには中心点情報が無いので、geometryを取得 geo :adsk.core.Circle3D = circle.worldGeometry # 単位を正しくしたい為、係数取得 unitsMgr :adsk.core.UnitsManager = des.unitsManager defLenUnit :str = unitsMgr.defaultLengthUnits covunit :float = unitsMgr.convert(1, unitsMgr.internalUnits, defLenUnit) # --情報収集-- infos = [] # 選択円 infos.append(isNativeMsg(circle)) ctr :adsk.core.Point3D = geo.center infos.append('中心座標:{}\n'.format('X: {1}{0} Y: {2}{0} Z: {3}{0}'.format( defLenUnit, ctr.x * covunit, ctr.y * covunit, ctr.z * covunit))) # 所属スケッチ skt :adsk.fusion.Sketch = circle.parentSketch infos.append(isNativeMsg(skt)) infos.append('所属スケッチ名:{}\n'.format(skt.name)) # 所属オカレンス occ :adsk.fusion.Occurrence = skt.assemblyContext infos.append(isNativeMsg(occ)) infos.append('所属オカレンス名:{}'.format(occ.name)) infos.append('道のり:ルート+{}'.format(occ.fullPathName)) # 情報表示 ui.messageBox('\n'.join(infos)) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) # ユーザーによる選択 def selectEnt( msg :str, filtterStr :str ) -> adsk.core.Selection : app :adsk.core.Application = adsk.core.Application.get() ui :adsk.core.UserInterface = app.userInterface try: sel = ui.selectEntity(msg, filtterStr) return sel except: return None # NativeObjectチェック def isNativeMsg(obj) -> str: if hasattr(obj, 'name'): name = obj.name else: name = '選択円' if not hasattr(obj, 'nativeObject'): return '[{}] は、NativeObjectの判断が出来ません'.format(name) if obj.nativeObject: return '[{}] は、NativeObjectではありません'.format(name) else: return '[{}] は、NativeObjectです'.format(name)
前回の最後に試した円と同じものを選択した結果がこちらです。
中心座標だけではなく、NativeObject情報やスケッチ・オカレンス名、
円の所属しているオカレンスまでの道のり等も表示させてみました。
(細かな例外処理していない為、ルートコンポーネントの円を選択すると
エラーになります)
何をお伝えしたかったかと言うと、selectEntityを使用して選択されたオブジェクトは
前回までグズグズ説明していたNativeObjectとProxyをあまり意識する必要がなく、
常にProxy(オカレンスを考慮した状態)が取得出来るようです・・・恐らく。
(どの要素が選択されたか?が明確なのでNativeObjectとは成らないはず)
長々と説明してきたNativeObjectとProxyのお話は今回でおしまいです。
正直に書くと、ここまでやってても未だに理解しきれていません。
実はHelpのここにキッチリと記載されています。
Fusion 360 Help
但し、裏切られた結果が返ってくるようなコードを実際に動かし、座標値のように
数字で結果を見ながら修正していく方が、理解しやすいかな?とは思っています。
結構複雑な仕組みとなっているため、非常に混乱しますが避けて通れない事を実感しています。
しかも、理解したつもりなのに裏切られる結果となる事もシバシバ・・・。
自身の理解も深まりました。
でも、"NativeObject" と "ProxyObject" (又は Native) と用語を揃えないのかな? 謎。