マリオネット・スクリプト解説講座

第53回「VectorScriptの中でPythonを使う」

FundamentalsArchitectLandmarkSpotlightDesigner

今回はスクリプトのマニアックな内容です。VectorScriptのスクリプトの中でPythonのスクリプトを実行する方法をご紹介します。

VectorScriptのスクリプトの中でPythonのスクリプトを実行できることをご存知でしょうか。

VectorScriptはVectorworksに特化した言語ですので、Vectorworksで作図や操作を命令する場合には最適な言語です。一方でデータの処理やOSへのアクセスなど汎用性ではPythonに軍配が上がります。

いずれも一長一短ありますが、VectorScriptとPythonを組み合わせることで、それぞれの言語の長所を活かしたプログラムを作成することができます。

53-1. PythonExecute

PythonExecuteリファレンス

PythonExecuteは、VectorScript(以下VS)の中でPythonのスクリプトを実行するための手続きです。Pythonのスクリプトを文字列で渡すことで、Pythonのスクリプトを実行することができます。

まずはお馴染みの「Hello, World!」をPythonで標準出力するVSスクリプトを作成します。

Procedure test;
Var
    pythonstring : Dynarray of Char;
Begin
    pythonstring := 'print("Hello, World!")';
    PythonExecute( pythonstring );
End;
Run( test );

上記のスクリプトを実行すると、VSの実行中にPythonのスクリプトが実行され、標準出力に「Hello, World!」が表示されます。

53-2. 複数行のPythonスクリプト

複数行のスクリプトを実行する場合は、PythonExecuteに渡す文字列自体を改行して記述します。例として、VSでは取得できない、OSの詳しい情報を拾うスクリプトを作成します。

Procedure test;
Var
    pythonstring : Dynarray of Char;
Begin
    pythonstring := '
import os
import sys
import platform
print(platform.system())
print(os.name)
print(sys.platform)
print(platform.release())
print(platform.version())
print(platform.platform())
';
    PythonExecute( pythonstring );
End;
Run( test );

Pythonのインデントを意識する必要があるため、格好良く書くことは難しそうです。

macOSでの実行結果となります。intelチップのMacなのか、MシリーズのMacなのかを見分けることができます。

インデントが必要な場合は文字列の中に含める必要があります。また、VSの中のPythonの中でもvs.**から始まるVSの関数を使用することができます。

Procedure test;
Var
    pythonstring : Dynarray of Char;
Begin
    pythonstring := '
import vs
import platform

if "arm" in platform.platform():
    vs.AlrtDialog( "MシリーズのMacです。" )
else:
    vs.AlrtDialog( "IntelのMacです。" )
';
    PythonExecute( pythonstring );
End;
Run( test );

53-3. 値の受け渡し

VSで使用している変数をPythonに渡して使用する方法を解説します。

53-3-1. 文字列に埋め込む

単純にPythonExecuteに渡す文字列に値を連結してしまう方法です。文字列の連結にはConcatを使用します。

VSで使用している2つの整数値について、Pyhtonでの最大公約数を求めてみます。

Procedure test;
Var
    value1, value2 : Integer;
    pythonstring : Dynarray of Char;
Begin
    value1 := 28;
    value2 := 42;
    pythonstring := Concat('
import vs
import math
value1_py =', Num2Str(0,value1),'
value2_py =', Num2Str(0,value2),'
gcd = math.gcd( value1_py, value2_py )
vs.AlrtDialog( f"最大公約数は:{gcd}" )
');
    PythonExecute( pythonstring );
End;
Run( test );

53-3-2. リポジトリを使う

起動中のVWアプリが確保しているメモリ領域(リポジトリ)にデータを保存する方法です。Rpstr_***で始まる名前の関数はリポジトリにアクセスするために用意されたものです。

    • Rpstr_GetValueBool
    • Rpstr_SetValueBool
    • Rpstr_GetValueStr
    • Rpstr_SetValueStr

など、値の型ごとに取得・保存の関数が用意されています。

Procedure test;
Var
    value1, value2 : Integer;
    pythonstring : Dynarray of Char;
Begin
    value1 := 28;
    value2 := 42;
    Rpstr_SetValueInt('value1_vs', value1);
    Rpstr_SetValueInt('value2_vs', value2);
    pythonstring := Concat('
import vs
import math
value1_py = vs.Rpstr_GetValueInt("value1_vs", 0)
value2_py = vs.Rpstr_GetValueInt("value2_vs", 0)
gcd = math.gcd( value1_py, value2_py )
vs.AlrtDialog( f"最大公約数は:{gcd}" )
');
    PythonExecute( pythonstring );
End;
Run( test );

PythonExecuteではデータの流れはVSからPythonへの一方通行を想定されていますが、リポジトリを使えば、Pythonの実行結果をVSで取得することができます。

Procedure test;
Var
    value1, value2, value3 : Integer;
    pythonstring : Dynarray of Char;
Begin
    value1 := 28;
    value2 := 42;
    Rpstr_SetValueInt('value1_vs', value1);
    Rpstr_SetValueInt('value2_vs', value2);
    pythonstring := Concat('
import vs
import math
value1_py = vs.Rpstr_GetValueInt("value1_vs", 0)
value2_py = vs.Rpstr_GetValueInt("value2_vs", 0)
gcd = math.gcd( value1_py, value2_py )
vs.Rpstr_SetValueInt("value3_vs", gcd)
');
    PythonExecute( pythonstring );
    value3 := Rpstr_GetValueInt('value3_vs', 0);
    Message( value3 );
End;
Run( test );

53-4. Macチップ判定の関数化

紹介した値の受け渡しの方法を使って、Macのチップ判定を関数化してみましょう。MacのチップがArmかどうかの判定(True/False)だけをPythonから取得して、その他はVS側で処理するようにします。

Procedure test;
    Function isArmMac : Boolean;
    Var
        pythonstring : Dynarray of Char;
    Begin
        pythonstring := '
import vs
import platform
vs.Rpstr_SetValueBool("isArmMac", "arm" in platform.platform())
';
        PythonExecute( pythonstring );
        isArmMac := Rpstr_GetValueBool('isArmMac', False);
    End;
Begin
    if isArmMac then
        AlrtDialog( 'MシリーズのMacです。' )
    else
        AlrtDialog( 'IntelのMacです。' );
End;
Run( test );

53-5. 文字列置換

文字列の処理はPythonが得意な部分です。VSの文字列を渡して、Pythonで文字列の置換をする関数を作成します。

Procedure test;
Var
    vsstring : String;
    Function ReplaceString( str,old,new : String ) : String;
    Var
        pythonstring : Dynarray of Char;
    Begin
        pythonstring := Concat('
s = "',str,'"
s = s.replace( "',old,'", "',new,'" )
vs.Rpstr_SetValueStr( "ReplaceString", s )
');
        PythonExecute( pythonstring );
        ReplaceString := Rpstr_GetValueStr('ReplaceString', '');
    End;
Begin
    vsstring := '[aanda.co.jp](https://www.aanda.co.jp/)';
    AlrtDialog( vsstring );
    vsstring := ReplaceString( vsstring, 'aanda', 'vectorworks' );
    AlrtDialog( vsstring );
End;
Run( test );

VSのみで文字列置換をする場合には、PosSubStringなどを駆使して複雑なコードを書く必要がありますが、Pythonだとreplaceの1行だけで済みます。

インデントやファイルパスなどいくつか注意すべき点はありますが、VSとPythonを組み合わせることで、確実にできることが増えます。「これはVectorScriptじゃないとできない、あれはPythonじゃないとできない」という課題も一挙に解決できる手段ですので、開発の実務でも頻繁に使用しています。VWにPythonが実装されて久しいですが、研究するほどに奥深さに気づくことができて楽しいですね。

この機能を利用できる製品

Fundamentals

Vectorworks Fundamentals

2D/3D汎用作図機能に、プレゼンボード作成機能や図面と連動できる表計算機能など、数多くの基本作図機能に加え、高品質レンダリング&3Dビジュアライズ機能を搭載したVectorworksシリーズの基本製品
詳細情報 購入ページ

Architect

Vectorworks Architect

建築設計や内装、ディスプレイデザインに対応した先進的なBIM・インテリア設計支援機能、拡張機能、さらには豊富な建築向けのデータライブラリを搭載した建築/内装業界向け製品
詳細情報 購入ページ

Landmark

Vectorworks Landmark

地形モデルや多彩な植栽、灌水設備計画等に対応するランドスケープデザイン機能、さらには豊富な造園向けのデータライブラリを搭載した都市計画/造園業界向け製品
詳細情報 購入ページ

Spotlight

Vectorworks Spotlight

ステージプランニングやライティング計画に対応した先進的な舞台照明計画支援機能、さらには各種メーカー製のトラスや照明機材、音響機器等の豊富なデータライブラリを搭載したエンタテインメント業界向け製品
詳細情報 購入ページ

Designer

Vectorworks Design Suite

専門分野別(建築設計/ディスプレイデザイン、ランドスケープデザイン、ステージデザイン&スポットライトプランニング)の設計支援機能、拡張機能、さらには豊富なデータライブラリを搭載した最上位の製品
詳細情報 購入ページ