C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

プロダクトからCATPartを生成2

こちらの続きです。
プロダクトからCATPartを生成 - C#ATIA

CATPartを生成しつつ、Igesでエクスポートします。
・・・Stepのライセンス無いのでIgesですが、同じでしょう。

'vba プロダクトからCATPartを生成しつつIgesでエクスポート
'この辺を参考にしました
'https://ww3.cad.de/foren/ubb/Forum137/HTML/005735.shtml
'https://www.scripting4v5.com/additional-articles/catia-macro-sendkeys/

Private Const EXPORT_DIR = "C:\temp\"

Sub CATMain()

    Dim prodDoc As ProductDocument
    Set prodDoc = CATIA.ActiveDocument

    Dim prod As Product
    Set prod = prodDoc.Product

    'プロダクトからCATPartを生成の実行
    Dim partDoc As PartDocument
    Set partDoc = execProd2Part(prod)

    'Igesで保存
    Dim exportPath As String
    exportPath = EXPORT_DIR & prod.Name & "_2Part"
    Call partDoc.ExportData(exportPath, "igs")

    '閉じる
    partDoc.Close
    
    'おしまい
    MsgBox "done"

End Sub

'プロダクトからCATPartを生成を実行し
'結果のPartDocumentを返す
Private Function execProd2Part( _
    ByVal prod As Product) _
    As PartDocument
    
    Dim prodDoc As ProductDocument
    Set prodDoc = prod.Parent
    
    '現在のドキュメント数
    Dim docCount As Long
    docCount = CATIA.Documents.Count
    
    'Treeのトップを選択
    Dim sel As Selection
    Set sel = prodDoc.Selection
    
    CATIA.HSOSynchronized = False
    
    sel.Clear
    sel.Add prod

    'プロダクトからCATPartを生成
    CATIA.StartCommand "CATProductToPartCmdHeader"
    CATIA.RefreshDisplay = True
    
    'OKボタン - VBAエディタでも大丈夫
    Dim WSShell
    Set WSShell = CreateObject("WScript.Shell")

    WSShell.SendKeys "c:FrmActivate"
    WSShell.SendKeys "{ENTER}"

    CATIA.HSOSynchronized = True

    'ドキュメントが増えるまで待機
    Do Until CATIA.Documents.Count > docCount
        DoEvents 'めっちゃ重要
    Loop

    Set execProd2Part = CATIA.ActiveDocument

End Function

不安ながら出来てます・・・多分。

OKボタンを押すのは

SendKeys "{Enter}"

より、こちらの方が安定していました。

又、ネックになっていた事が

    'ドキュメントが増えるまで待機
    Do Until CATIA.Documents.Count > docCount
        DoEvents 'めっちゃ重要
    Loop

で、解決しました。


非同期処理についてですが、薄ら記憶はあったので調べてみた所
こちらのExecuteBackgroundProcessusが該当します。
r1 SystemService (Object)
試してはいないのですが、但しHelpの記載からGUIのCATIAからは
失敗しそうな雰囲気を感じます。
かといってバッチ起動のCATIAで "{ENTER}" が成功する雰囲気を
全く感じない為、”無理だろうな” と勝手な判断しました。

プロダクトからCATPartを生成1

勘違い。
過去にやったことがあったのは、CATPartをBody毎にした
CATProductにする逆の事でした。
1つのPartからBody毎にしたProductを作り出す - C#ATIA

で、本題の "プロダクトからCATPartを生成" ですが、結果的に
"CATIA.StartCommand" を使うしか方法が無さそうです。

'vba プロダクトからCATPartを生成
'この辺を参考にしました
'https://ww3.cad.de/foren/ubb/Forum137/HTML/005735.shtml
'https://www.scripting4v5.com/additional-articles/catia-macro-sendkeys/
Sub CATMain()

    'Treeのトップを選択
    Dim prodDoc As ProductDocument
    Set prodDoc = CATIA.ActiveDocument
    
    Dim prod As Product
    Set prod = prodDoc.Product
    
    Dim sel As Selection
    Set sel = prodDoc.Selection
    
    sel.Clear
    sel.Add prod

    'プロダクトからCATPartを生成
    CATIA.StartCommand "CATProductToPartCmdHeader"
    CATIA.RefreshDisplay = True
    SendKeys "{Enter}"

End Sub

念の為お伝えすると、VBAエディタで実行すると、コマンドの
ダイアログが表示された状態で止まってしまいますが、
ツールバーに登録する等して実行すると、きっちり処理します。

又、"CATProductToPartCmdHeader"はコマンドIDの為、
CATIA V5の言語設定に依存せず、実行できます。

不要なものを除去しつつフォルダのコピー

innoSetupでインストーラーを作成する際に面倒な為、
フォルダを指定しているのですが、当然不要なフォルダーや
ファイルまでもがインストーラーに入ってしまいます。

別に動作には影響ないのですが、要らないものを配布するのも
気が引けるので、何とかします。

試していないのですが、innoSetupはインストーラを作成する
前後にプログラムを実行することが出来るっぽいので、
作戦としては、
・不要なものを除去しつつフォルダのコピー
・コピーしたフォルダを元にインストーラー作成
・コピーしたフォルダを削除
だと手間が省けそうな気がしてます。

で、表題の処理を行うスプリクトを作りました。
何で作るべきか悩みましたが、VBScriptにしました。

'必要なものでだけのフォルダーコピー
call Main()

sub Main()
    removeFolderNames = array(".vscode", "temp", "__pycache__")
    removeFileNames = array(".env")

    targetDir = "Fusion360_NEKONOTE\NEKONOTE"
    tempDir = getTempPath()

    'copy
    Call copyFolder(targetDir, tempDir)

    'get remove folder&file
    Dim removeLst
    Set removeLst = CreateObject("System.Collections.ArrayList")
    for idx = 0 to ubound(removeFolderNames)
        removeLst.AddRange(getFolderPaths(tempDir & "\NEKONOTE", removeFolderNames(idx)))
    next
    for idx = 0 to ubound(removeFileNames)
        removeLst.AddRange(getFilePaths(tempDir & "\NEKONOTE", removeFileNames(idx)))
    next

    'remove folders
    call execRemove(removeLst)
end sub

sub execRemove(lst)
    On Error Resume Next
    for each path in lst
        path.Delete
    next
end sub

'return ArrayList
function getFilePaths(path, removeName)
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set folder = fso.GetFolder(path)

    Dim stack
    Set stack = CreateObject("System.Collections.ArrayList")
    call stack.add(folder)

    dim lst
    Set lst = CreateObject("System.Collections.ArrayList")

    Do Until stack.Count = 0
        set folder = stack.item(0)
        for each f in folder.Files
            if f.Name = removeName then
                lst.add(f)
            end if
        next
        for each sf in folder.SubFolders
            stack.add(sf)
        next
        stack.RemoveAt(0)
    loop

    set getFilePaths = lst
end function

'return ArrayList
function getFolderPaths(path, removeName)
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set folder = fso.GetFolder(path)

    Dim stack
    Set stack = CreateObject("System.Collections.ArrayList")
    call stack.add(folder)

    dim lst
    Set lst = CreateObject("System.Collections.ArrayList")

    Do Until stack.Count = 0
        set folder = stack.item(0)
        for each sf in folder.SubFolders
            if sf.Name = removeName then
                lst.add(sf)
            else
                stack.add(sf)
            end if
        next
        stack.RemoveAt(0)
    loop

    set getFolderPaths = lst
end function

sub copyFolder(targetDir, tempDir)
    Set fso = CreateObject("Scripting.FileSystemObject")
    Call fso.CopyFolder(targetDir, tempDir)
end sub

function getTempPath()
    Set fso = CreateObject("Scripting.FileSystemObject")
    getTempPath = fso.GetSpecialFolder(2).Path & "\"
end function

正確には、フォルダを丸ごとコピーして、不要なファイル・フォルダ
をチマチマ削除してます。

アドイン完成しているのに、それ以外の部分で手間取っている。

Inno Setup その2

こちらの続きです。
Inno Setup - C#ATIA


Inno Setup、中々悩みました。でも何とかなりそう。

基本的にこちらを参考にさせて頂きました。
【InnoSetupの使い方】インストーラー作成方法の紹介 - Useful Edge

幾つか悩んだ部分の覚書。


赤部はアドイン名です。後にインストール(コピー)する
フォルダを指定しますが、フォルダ自体はインストール後
コピーされていませんでした。
pyファイル名と一致させる必要がある為、アドイン名です。



インストール先となるフォルダのデフォルトの指定ですが、
可能であれば、Fusion360のアドインのデフォルトフォルダと
したいです。
赤部は”custom”として青部にパスを指定します。

しかしそのパスは、Winの場合はユーザープロファイルの下に
なっている為、どの様に指定して良いものか分かりませんでした。
で、結局この様にすると、目的のパスになりました。

DefaultDirName={%USERPROFILE}\AppData\Roaming\Autodesk\Autodesk Fusion 360\API\AddIns\{#MyAppName}



Fusion360のアドインの為、実行ファイルではありません。
その為、赤部にチェックを入れると青部がグレーアウトします。
その分、緑部でフォルダを指定。 が良いんじゃないのかな?


innoSetupのファイル(.iss)自体は単なるテキストファイルでした。
ウィザード実行後、適当に編集して正しくない状態でコンパイル
した際、余裕でウィルスチェックが動作します・・・。
まぁインストーラが作られているのだから、ウィルスと大差無い
ものになるよね。

innoSetupが日本語化出来ない事もあり、ウィザードも中々やり
にくい。issファイルが単なるテキストファイルだと考えれば、
issファイルを作るためのスクリプト/アドイン作った方が
楽かも知れない・・・。

Inno Setup

Winのみだけど、インストーラーも用意したいのですが
手探りです。 こちらでEkins氏がお勧めしているのが
Inno Setupでした。
Re: How to share an AddIn? - Autodesk Community

普通にWin用として検索しても上位でヒットしました。
毎回調べるので、覚書です。
【InnoSetupの使い方】インストーラー作成方法の紹介 - Useful Edge

Flexbox

Flexboxなるレイアウト用の技術がある事を知りました。
フレックスボックスの基本概念 - CSS: カスケーディングスタイルシート | MDN

対応ブラウザを調べていてもFusion360のパレットに
使用されているQT Web Browserが出ていないので
試してみました。

レスポンシブに対応してそうです。
一番苦手なCSSか・・・。もう覚えきれない。

開発者向けアドイン12

こちらの続きです。
開発者向けアドイン11 - C#ATIA

ボリュームが大きくなりすぎた為、単体のプロジェクトとし
公開しました。
GitHub - kantoku-code/Fusion360_Developers_Small_ToolKit: 通常のユーザーには、ほぼ無意味なFusion360 API 開発者向けの小さな工具箱

見た目はあまり変わっていませんが・・・と言うより
なるべく変わらないように中身を大幅に変更? いや
作り直しました。

機能的には "Dump OKN""Open Install Folder"の2つの
コマンドを追加しましたが、他の方にはあまり必要の
無いものばかりです。

あぁ楽。機能追加するのがめっちゃ楽。