ARCHICADBIM開発
Tapirにコマンドを追加する方法【Archicad】
2025.11.19
2025.11.19
こんにちは IU BIM Studioの原田です。
今回は前回紹介したTapirに独自のコマンドを追加する方法を説明します。
Tapirについては前回の記事も参照ください
Tapirでコマンドを追加するにはArchicad アドオンを作成する必要があります。
アドオンを1から作成するわけではなく、Tapirのコードに追加したいコマンドのコードを記述します。
Tapirはオープンソースになっており、ソースコードが公開されています。
MITライセンスになっているため、制約は緩い方かと思います。
MITライセンスはざっくりいうと「コードを利用していいけど、トラブルがあっても責任取りませんよ」というライセンスかと思います。詳しくは各自で調べていただければと思います。
プログラム言語はC++になり、少しハードルが高いですが、TapirをカスタマイズできるようになるとPythonでできることが増えます。
今回は例として、TapirからArchicadのバージョンを取得する方法を説明します
まずはTapirのリポジトリをクローンします
git clone https://github.com/ENZYME-APD/tapir-archicad-automation.gitArchicadアドオンに関するコードはクローンした中のarchicad-addonフォルダの中にあります。
Visual Studioで編集するために、Visual Studioのプロジェクトを作成する必要がありますが、今回はVisual Studio周りの設定方法は省略します。
では、コマンドを追加していきましょう。
既存のコードと分けるため、ヘッダファイルとソースファイルを新規作成します。
ここではMyCommands.hppとMyCommands.cppとします。
ここからコマンド追加の作業に入りますが、1から作成するよりも似たような内容のコマンドをコピー&ペーストしたほうが早いでしょう。
今回はArchicadのバージョンを取得したいので、そこまで複雑なものではありません。ApplicationCommandsのGetAddOnVersionCommnadなどが良いでしょう。まずはヘッダファイルからです。
#pragma once
#include "CommandBase.hpp"
class GetAddOnVersionCommand : public CommandBase
{
public:
GetAddOnVersionCommand ();
virtual GS::String GetName () const override;
virtual GS::Optional<GS::UniString> GetResponseSchema () const override;
virtual GS::ObjectState Execute (const GS::ObjectState& parameters, GS::ProcessControl& processControl) const override;
};Tapirでは作成したいコマンドごとにクラスを作成します。
クラスはCommandBaseクラスを継承して作成します。
クラス内のメソッドを見ていきましょう。内容としては下記のような内容のようです。
入力データを送信する必要があるコマンドの場合はGetInputParametersSchemaというメソッドで入力フォーマットを指定する必要がありますが、今回は必要ありません。
ではコピーした先のクラス名を変えます。
#pragma once
#include "CommandBase.hpp"
class GetArchicadVersionCommand : public CommandBase
{
public:
GetArchicadVersionCommand ();
virtual GS::String GetName () const override;
virtual GS::Optional<GS::UniString> GetResponseSchema () const override;
virtual GS::ObjectState Execute (const GS::ObjectState& parameters, GS::ProcessControl& processControl) const override;
};クラス名を新しいものに変え、それに合わせてコンストラクタの名前も変えます。
ヘッダファイルの変更は以上です。
では、ソースファイルを変えていきます。こちらも同じ部分からコピーします。
MyCommands.hppをインクルードしておきます。
#include "MyCommands.hpp"
GetAddOnVersionCommand::GetAddOnVersionCommand () :
CommandBase (CommonSchema::NotUsed)
{
}
GS::String GetAddOnVersionCommand::GetName () const
{
return "GetAddOnVersion";
}
GS::Optional<GS::UniString> GetAddOnVersionCommand::GetResponseSchema () const
{
return R"({
"type": "object",
"properties": {
"version": {
"type": "string",
"description": "Version number in the form of \"1.1.1\".",
"minLength": 1
}
},
"additionalProperties": false,
"required": [
"version"
]
})";
}
GS::ObjectState GetAddOnVersionCommand::Execute (const GS::ObjectState& /*parameters*/, GS::ProcessControl& /*processControl*/) const
{
return GS::ObjectState ("version", ADDON_VERSION);
}では、まずクラス名を修正しましょう。
コンストラクタの名前も変えておきます。
GetArchicadVersionCommand::GetArchicadVersionCommand () :
CommandBase (CommonSchema::NotUsed)
{
}
GS::String GetArchicadVersionCommand::GetName () const
{
return "GetAddOnVersion";
}
GS::Optional<GS::UniString> GetArchicadVersionCommand::GetResponseSchema () const
{
return R"({
"type": "object",
"properties": {
"version": {
"type": "string",
"description": "Version number in the form of \"1.1.1\".",
"minLength": 1
}
},
"additionalProperties": false,
"required": [
"version"
]
})";
}
GS::ObjectState GetArchicadVersionCommand::Execute (const GS::ObjectState& /*parameters*/, GS::ProcessControl& /*processControl*/) const
{
return GS::ObjectState ("version", ADDON_VERSION);
}
次に、GetNameメソッドを修正します。
GS::String GetArchicadVersionCommand::GetName () const
{
return "GetArchicadVersion";
}これは名前を変えるだけです。
クラス名からCommandを除いたものにするのがルールっぽいのでそれに倣います。
これがTapirから呼び出すときのコマンド名になっていると思われます。
次にGetResponseSchemaメソッドを修正します。
GS::Optional<GS::UniString> GetArchicadVersionCommand::GetResponseSchema () const
{
return R"({
"type": "object",
"properties": {
"version": {
"type": "string",
"description": "Version number in the form of \"28.0.0\".",
"minLength": 1
}
},
"additionalProperties": false,
"required": [
"version"
]
})";
}今回は同じようなコマンドから作ったので特に修正はありません。直すとすればdescriptionのところでしょうか。サンプルデータをArchicadのバージョンに直しておきましょう。
このスキーマに従ってコマンドの戻り値を返します。今回は簡単なのでよかったですが、複雑になると結構大変ですね。
一応スキーマの再利用ができるようになっているらしく、その内容はCommonSchemaDefinitions.jsonに記述されています。
こちらに追記することで独自のデータ形式を追加することも可能です。
次にExecuteメソッドを修正します。
#include "ACAPI/LicenseInfo/LicenseInfoManager.hpp"
GS::ObjectState GetArchicadVersionCommand::Execute (const GS::ObjectState& /*parameters*/, GS::ProcessControl& /*processControl*/) const
{
ACAPI::Result<ACAPI::LicenseInfo::LicenseInfoManager> licenseInfo = ACAPI::LicenseInfo::GetLicenseInfoManager ();
GS::UniString version = licenseInfo.Unwrap ().GetProductVersionInfo ().GetVersionString ();
return GS::ObjectState ("version", version);
}
このメソッドが出力する情報を作成する部分です。この出力がResponseSchemaと一致している必要があります。今回はArchicadのバージョンを返すだけなので特に難しいところはありません。
最後にコマンドを登録します。
コマンドを登録しておかないと使うことができません。
コマンドの登録はAddOnMain.cpp内のInitialize関数の中で行います。
まずはAddOnMain.cppにMyCommands.hppをインクルードします。
次にInitialize関数内でコマンドを登録します。
基本的には他のコマンドに倣っておけば大丈夫だとおもいます。
GSErrCode Initialize (void){
// 中略
{ // Custom Commands
CommandGroup customCommands ("My Commands");
err |= RegisterCommand<GetArchicadVersionCommand> (
customCommands, "1.0.0",
"Get Archciad Version"
);
AddCommandGroup (customCommands);
}
}
追加したコマンドが使えるかを確認します。
プロジェクトを開き、適当な画面で待機します。
次に呼び出し側のコードをpythonで作成します。詳しくは前回の内容をご確認ください。
from archicad import ACConnection
conn: ACConnection = ACConnection.connect()
acc = conn.commands
act = conn.types
def run_tapir_command(command: str, param: dict= None) -> dict:
addOnCommandId = act.AddOnCommandId("TapirCommand", command)
result = acc.ExecuteAddOnCommand(addOnCommandId, param)
return result
result = run_tapir_command("GetArchicadVersion")
print(result)
# {'version': '28.0.0'}
Archicadのバージョンがjson形式で受け取れました。
マイナーバージョンが実際のものと合っていないのは、API側のバグでしょうかね…?
今回はPython側と通信できたことで良しとしましょう。
以上で、Tapirにコマンドを追加することができました。
Tapirにコマンドを追加できるとPythonでコードを書けばすむようになるので、ケースによってはとても楽になります。ただ、全てのコマンドを追加するのは大変なので、どういう目的でどのようなデータを使うのか考えることが大事ですね。
今回は以上です。
最後までお読みいただきありがとうございました。
最後にコードを載せおきます。
・MyCommands.hpp
#pragma once
#include "CommandBase.hpp"
class GetArchicadVersionCommand : public CommandBase
{
public:
GetArchicadVersionCommand ();
virtual GS::String GetName () const override;
virtual GS::Optional<GS::UniString> GetResponseSchema () const override;
virtual GS::ObjectState Execute (const GS::ObjectState& parameters, GS::ProcessControl& processControl) const override;
};・MyCommands.cpp
#include "MyCommands.hpp"
#include "ACAPI/LicenseInfo/LicenseInfoManager.hpp"
GetArchicadVersionCommand::GetArchicadVersionCommand () :
CommandBase (CommonSchema::NotUsed)
{}
GS::String GetArchicadVersionCommand::GetName () const
{
return "GetArchicadVersion";
}
GS::Optional<GS::UniString> GetArchicadVersionCommand::GetResponseSchema () const
{
return R"({
"type": "object",
"properties": {
"version": {
"type": "string",
"description": "Version number in the form of \"28.0.0\".",
"minLength": 1
}
},
"additionalProperties": false,
"required": [
"version"
]
})";
}
GS::ObjectState GetArchicadVersionCommand::Execute (const GS::ObjectState& /*parameters*/, GS::ProcessControl& /*processControl*/) const
{
ACAPI::Result<ACAPI::LicenseInfo::LicenseInfoManager> licenseInfo = ACAPI::LicenseInfo::GetLicenseInfoManager ();
GS::UniString version = licenseInfo.Unwrap ().GetProductVersionInfo ().GetVersionString ();
return GS::ObjectState ("version", version);
}・AddOnMain.cpp
// 省略
#include "MyCommands.hpp"
// 省略
GSErrCode Initialize (void){
// 省略
{ // Custom Commands
CommandGroup customCommands ("My Commands");
err |= RegisterCommand<GetArchicadVersionCommand> (
customCommands, "1.0.0",
"Get Archciad Version"
);
AddCommandGroup (customCommands);
}
}
// 省略・Python(呼び出し側)
from archicad import ACConnection
conn: ACConnection = ACConnection.connect()
acc = conn.commands
act = conn.types
def run_tapir_command(command: str, param: dict = None) -> dict:
addOnCommandId = act.AddOnCommandId("TapirCommand", command)
result = acc.ExecuteAddOnCommand(addOnCommandId, param)
return result
result = run_tapir_command("GetArchicadVersion")
print(result)

ARCHICADBIM開発
2025.11.19

ARCHICADBIMPython開発
2025.10.29

BIMお知らせ
2025.10.14

ARCHICADBIMPython開発
2025.09.24

ARCHICADBIMGrasshopperPython開発
2025.08.25

BIMGrasshopper
2025.07.23