「VRM ONLINE」カテゴリーアーカイブ

VRMONLINE-NX Pythonモジュールの検索パス

NXシステムの組み込みPythonには、標準的なモジュールライブラリを用意しています。さらにモジュールを拡張する場合は、WindowsにインストールしたPythonをモジュールの検索パスに追加します。

#レイアウトスクリプトに記述
import sys

sys.path.append("C:\Python37\Lib")
sys.path.append("C:\Python37\Lib\site-packages")

#このあとに追加した検索パスから読み込むモジュールをimportする

sysをimportして、sys.pathにモジュールの検索パスを追加します。追加する検索パスは、WindowsにインストールしたPythonのパスを指定します。

“Lib”の他に”Lib/site-packages”を追加してください。pipでインストールしたモジュールもimportできます。さらに必要に応じてDLLsも検索パスに追加してください。

検索パスを追加した環境でimportした場合、環境依存になります。レイアウトを公開する場合はご注意ください。

VRMONLINE 緊急メンテのご案内

平素は鉄道模型シミュレーターオンラインをご利用いただきまことにありがとうございます。

本日17時より1時間ほど、鉄道模型シミュレーターオンラインのデータベースアップグレード作業を実施します。

メンテナンス実施中は、鉄道模型シミュレーターオンラインおより関連webサイトはご利用いただくことができません。大変ご面倒をおかけいたしますが、作業完了までお待ちいただけますようお願い申し上げます。

VRMONLINE-NX スクリプトでゲームパッド

βテストにご参加いただきまことにありがとうございます。

ビルド60にて追加したゲームパッド関数のサンプルです。

ゲームパッドは、最大4台をPCに接続、スクリプトから認識することができます。

IsGamepadConnected()関数は、ゲームパッドが接続されているか確認します。
デバイス番号を0から3のいずれか1つで指定、当該デバイスが接続されていればTrueを返します。

GetGamepad系関数は、ボタンが押されていた場合、Trueを返します。この関数もデバイス番号を指定します。

AnalogStick関数は、16ビットの符号付き整数で傾き具合を返します。

サンプルは、編成スクリプトのframeイベントでゲームパッドの状態を表示するウィンドウを開いています。
このビルドからSYSTEM()関数を追加しました。この関数はLAYOUT().SYSTEM()と同じ動作です。記述を短縮できます。

#OBJID=6
import vrmapi

def vrmevent_6(obj,ev,param):
    if ev == 'init':
        obj.SetEventFrame()
    elif ev == 'broadcast':
        dummy = 1
    elif ev == 'timer':
        dummy = 1
    elif ev == 'time':
        dummy = 1
    elif ev == 'after':
        dummy = 1
    elif ev == 'frame':
        vrmapi.ImGui().Begin("w1","Sample")
        vrmapi.ImGui().Text( "pad0-> " + str(vrmapi.SYSTEM().IsGamepadConnected(0)) )
        vrmapi.ImGui().Text( "pad1-> " + str(vrmapi.SYSTEM().IsGamepadConnected(1)) )

        vrmapi.ImGui().Text( "[0]-A " + str(vrmapi.SYSTEM().GetGamepadA(0)) )
        vrmapi.ImGui().Text( "[0]-B " + str(vrmapi.SYSTEM().GetGamepadB(0)) )
        vrmapi.ImGui().Text( "[0]-X " + str(vrmapi.SYSTEM().GetGamepadX(0)) )
        vrmapi.ImGui().Text( "[0]-Y " + str(vrmapi.SYSTEM().GetGamepadY(0)) )

        vrmapi.ImGui().Text( "[0]-Analog L " + str(vrmapi.SYSTEM().GetGamepadAnalogStickLY(0)) )
        vrmapi.ImGui().Text( "[0]-Analog R " + str(vrmapi.SYSTEM().GetGamepadAnalogStickRY(0)) )

        vrmapi.ImGui().End()
    elif ev == 'couple':
    #以下省略

VRMONLINE-NX ゲームパッド対応

ビルド60にて、ゲームパッドに対応しました。Windows標準のゲームパッドがご利用いただけます。

上下速度調整、ノッチ変更
A警笛
B進行方向
Xオフセット操作リセット
Y制御装置切り替え
LB/RB外部カメラ:左右移動
運転台カメラ:回転

ビュワーのカメラ視点は、「運転台モード」と「外部カメラ」があります。運転台モードは、運転席からの視点に対応しています。運転席からのカメラオフセット操作は、回転操作がメインになります。

Pythonでは、ゲームパッドの状態値を取得できます。ゲームパッドのボタンごとにマスクをかけて、スクリプトでボタンを専有することもできます。(専有した場合、通常の操作が無効化されます。)
最大4台までのパッドをスクリプトで使うことができます。

VRMONLINE-NX スプライト演算

βテストにご参加いただきまことにありがとうございます。

スプライトに幾何学演算機能を追加しました。

スプライトを設定する場合、表示座標を直接指定する場合は、SetPos()を利用して下記の流れで指定します。
座標値は、Pythonで演算した結果を設定します。

SetUV() -> SetPos() -> SetSprite()

スプライトシステムに基本的な幾何学演算を依頼することもできます。

SetUV() -> SetZoom() -> SetRotate() -> SetTranslate() -> SetSprite()

この流れで拡大縮小、回転、移動を計算します。UVまたはOrg関数で指定した大きさの四角形を拡大縮小、回転、移動の順に計算します。
SetZoom()などは、演算パラメータの設定を行います。(関数の呼び出し時点で演算は実行しません。)

幾何学演算は、SetPos()とは排他的です。幾何学演算または直接指定のいずれか1つが使用されます。

SetColor()は、RGBAのそれぞれの強さを指定します。スプライトのテクスチャーに乗算します。
サンプルでは、RBを0にして、Gのみ表示しています。
シェーダーの合成演算によって結果が異なります。半透明にする場合は、RGBAのすべての要素を減らしてください。

#OBJID=6
import vrmapi

global tr_sprite
tr_rot = [0.0]
tr_win = [1]

def vrmevent_6(obj,ev,param):
    global tr_sprite
    global tr_rot
    global tr_win
    if ev == 'init':
        tr_sprite = vrmapi.LAYOUT().CreateSprite()
        tr_sprite.LoadTrainTexture(obj.GetID(), 1)
        obj.SetEventFrame()
    elif ev == 'broadcast':
        dummy = 1
    elif ev == 'timer':
        dummy = 1
    elif ev == 'time':
        dummy = 1
    elif ev == 'after':
        dummy = 1
    elif ev == 'frame':
        vrmapi.ImGui().Begin("w1","Sample", tr_win, vrmapi.ImGuiWindowFlags.MenuBar)

        vrmapi.ImGui().SliderFloat("sl1", "ROTATE", tr_rot, 0.0, 360.0)
        tr_sprite.SetUV(0,0,84,72)
        tr_sprite.SetPos(0,100,84*2,100,0,100+72*2,84*2,100+72*2)
        tr_sprite.SetSprite()
        tr_sprite.SetUV(0,78,128,78+44)
        tr_sprite.SetZoom(2.0,2.0)
        tr_sprite.SetRotate(0,0,tr_rot[0])
        tr_sprite.SetTranslate(450,300)
        tr_sprite.SetColor(0.0,1.0,0.0,1.0)
        tr_sprite.SetSprite()

        vrmapi.ImGui().End()
# 以下省略        
スライダーで回転

VRMONLINE-NX ウィンドウフラグ

βテストにご参加いただきまことにありがとうございます。

ビルド57にて、ImGuiのBegin()関数のフルバージョンをご用意しました。

ウィンドウのOpen状態を記録する変数とフラグが設定できます。

フラグはvrmapi.ImGuiWindowFlagsで指定します。
vrmapi.ImGuiWindowFlags.NoTitleBarでタイトルバーが非表示になります。
フラグはor演算で複数指定できます。

フラグ指定
#LAYOUT
import vrmapi

po1 = [0];
po2 = [0];

def vrmevent(obj,ev,param):
    if ev == 'init':
        obj.SetEventFrame()
    elif ev == 'broadcast':
        dummy = 1
    elif ev == 'timer':
        dummy = 1
    elif ev == 'time':
        dummy = 1
    elif ev == 'after':
        dummy = 1
    elif ev == 'frame':
        global po1;
        global po2;
        vrmapi.ImGui().SetNextWindowPos(0,60)
        vrmapi.ImGui().SetNextWindowSize(320,200)
        vrmapi.ImGui().SetNextWindowSizeConstraints(320,200,480,240)
        #タイトルバーなし
        vrmapi.ImGui().Begin("win10","Sample Window", po1, vrmapi.ImGuiWindowFlags.NoTitleBar)

        cpos = obj.SYSTEM().GetGlobalCameraPos()
        vrmapi.ImGui().Text("SYSカメラ座標 =>"+str(cpos[0])+"  "+str(cpos[2]))

        vrmapi.ImGui().End()

        vrmapi.ImGui().SetNextWindowPos(0,260)
        vrmapi.ImGui().SetNextWindowSize(480,120)
        vrmapi.ImGui().SetNextWindowSizeConstraints(480,120,480,120)
        #移動、リサイズ禁止
        vrmapi.ImGui().Begin("win11","2nd Window", po2, vrmapi.ImGuiWindowFlags.NoMove |  vrmapi.ImGuiWindowFlags.NoResize)
        vrmapi.ImGui().Text("第二ウィンドウ")
        vrmapi.ImGui().End()
    elif ev == 'keydown':
        dummy = 1

VRMONLINE-NX 編成でスプライト

βテストにご参加いただきまことにありがとうございます。

編成部品でスプライトを使用するサンプルスクリプトです。

485系クハの車両テクスチャーから、ヘッドマークと方向幕をスプライトで表示しています。
(車両テクスチャーは、部品の組み込みテクスチャーを保存して、編成リソースに登録してください。)

実装については、下記コードのコメントをご参照ください。

ヘッドマーク
(0,0)から84*72 pixel

方向幕
(0,78)から128*44 pixel

#OBJID=6
import vrmapi

#global変数でスプライトオブジェクトを格納する変数を宣言
global tr_sprite

def vrmevent_6(obj,ev,param):
    #global変数を使うことを指定
    global tr_sprite
    if ev == 'init':
        # initイベントでスプライトオブジェクトを生成
        # スプライトオブジェクトの生成は、LAYOUTの関数
        tr_sprite = vrmapi.LAYOUT().CreateSprite()
        # 編成のリソースからテクスチャーを読み込む
        # サンプルのテクスチャーは、リソース番号1
        tr_sprite.LoadTrainTexture(obj.GetID(), 1)
        # フレームイベントを設定
        obj.SetEventFrame()
    elif ev == 'broadcast':
        dummy = 1
    elif ev == 'timer':
        dummy = 1
    elif ev == 'time':
        dummy = 1
    elif ev == 'after':
        dummy = 1
    elif ev == 'frame':
        # スプライトは毎フレーム、設定する
        # UV, POSを指定して、SetSpriteで登録
        # 1枚めのスプライトを設定(ヘッドマーク)
        tr_sprite.SetUV(0,0,84,72)
        tr_sprite.SetPos(0,100,84*2,100,0,100+72*2,84*2,100+72*2)
        tr_sprite.SetSprite()
        # 2枚めのスプライトを設定(方向幕)
        tr_sprite.SetUV(0,78,128,78+44)
        tr_sprite.SetPos(0,300,128,300,0,300+44,128,300+44)
        tr_sprite.SetSprite()
    elif ev == 'couple':
        dummy = 1
# 以下省略
編成でスプライト

VRMONLINE-NX ウィンドウを二枚

βテストにご参加いただきまことにありがとうございます。

GUIウィンドウを2枚表示するスクリプトサンプルです。

imguiは、Begin()-End()で一枚のウィンドウを表示します。
複数のウィンドウを表示する場合は、Begin-Endを必要な個数並べます。

ウィンドウの表示位置は、SetNextWindowPos()で指定します。
Begin()より前に指定してください。

ウィンドウの大きさは、標準のBegin()で表示されるウィンドウが、表示サイズを自動で記憶するため、SetNextWindowSizeConstraints()で条件を縛ってください。
SetNextWindowSize()でサイズを指定、SetNextWindowSizeConstraints()でリサイズ可能な範囲を指定します。

標準以外のBegin()については、今後の拡張をお待ち下さい。

#LAYOUT
import vrmapi


def vrmevent(obj,ev,param):
    if ev == 'init':
        obj.SetEventFrame()
    elif ev == 'broadcast':
        dummy = 1
    elif ev == 'timer':
        dummy = 1
    elif ev == 'time':
        dummy = 1
    elif ev == 'after':
        dummy = 1
    elif ev == 'frame':
        vrmapi.ImGui().SetNextWindowPos(0,60)
        vrmapi.ImGui().SetNextWindowSize(320,200)
        vrmapi.ImGui().SetNextWindowSizeConstraints(320,200,480,240)
        vrmapi.ImGui().Begin("win10","Sample Window")

        cpos = obj.SYSTEM().GetGlobalCameraPos()
        vrmapi.ImGui().Text("SYSカメラ座標 =>"+str(cpos[0])+"  "+str(cpos[2]))

        if vrmapi.ImGui().Button("b1", "システムカメラ切り替えボタン"):
            if obj.IsViewGlobal():
                obj.SetViewGlobal(False)
            else:
                obj.SetViewGlobal(True)

        vrmapi.ImGui().End()

        vrmapi.ImGui().SetNextWindowPos(0,260)
        vrmapi.ImGui().SetNextWindowSize(480,120)
        vrmapi.ImGui().SetNextWindowSizeConstraints(480,120,480,120)
        vrmapi.ImGui().Begin("win11","2nd Window")
        vrmapi.ImGui().Text("第二ウィンドウ")
        vrmapi.ImGui().End()
    elif ev == 'keydown':
        dummy = 1
ウィンドウ表示サンプル

VRMONLINE-NX スクリプト仕様変更しました

βテストにご参加いただきまことにありがとうございます。

ビルド55を公開しました。

GetPosition()などのスクリプト関数の仕様を変更しました。仕様を変更した関数について、βテストご案内ページに一覧を掲載しています。
仕様変更にあわせて、スクリプトの書き換えをお願いします。

各関数の詳細は、スクリプトマニュアルをご参照ください。

GetPosition()は、データを関数の戻り値で返します。データは、list型です。

このバージョンでは、カメラモードについての関数を追加しています。SetViewGlobal()で、システムカメラの切り替えができます。

下記サンプルは、編成がID=5、地上カメラがID=8で設置したレイアウトのスクリプトです。

ボタンで、システムカメラの切り替え、表示対象を編成、地上カメラと切り替えることができます。

#LAYOUT
import vrmapi


def vrmevent(obj,ev,param):
    if ev == 'init':
        obj.SetEventFrame()
    elif ev == 'broadcast':
        dummy = 1
    elif ev == 'timer':
        dummy = 1
    elif ev == 'time':
        dummy = 1
    elif ev == 'after':
        dummy = 1
    elif ev == 'frame':
        vrmapi.ImGui().Begin("win1","Sample Window")
        vrmapi.ImGui().Separator()
        vrmapi.ImGui().Text("ボタンテスト")
        
        train = obj.GetTrain(5)
        tpos = train.GetPosition()
        vrmapi.ImGui().Text("編成座標 =>"+str(tpos[0])+"  "+str(tpos[2]))
        
        cpos = obj.SYSTEM().GetGlobalCameraPos()
        vrmapi.ImGui().Text("SYSカメラ座標 =>"+str(cpos[0])+"  "+str(cpos[2]))

        if vrmapi.ImGui().Button("b1", "システムカメラ切り替えボタン"):
            if obj.IsViewGlobal():
                obj.SetViewGlobal(False)
            else:
                obj.SetViewGlobal(True)

        if vrmapi.ImGui().Button("b3", "地上カメラ"):
                obj.SetView(8)
        if vrmapi.ImGui().Button("b4", "編成カメラ"):
                obj.SetView(5)

        if obj.IsViewGlobal():
            vrmapi.ImGui().Text("システムカメラ")


        vrmapi.ImGui().End()
    elif ev == 'keydown':
        dummy = 1
システムカメラに切り替え
地上カメラに切り替え
編成カメラに切り替え

GUIサンプル ツリーと数値入力

βテストにご参加いただきまことにありがとうございます。

次のサンプルは、GUIらしいギミックです。

GUI部品をそのまま多数並べると、見通しが悪くなります。
これを避けるためにGUI部品を目的ごとに分類、ツリー構造にします。

TreeNode()とTreePop()の組み合わせで、1つのツリーになります。
ツリーは親子構造にもできます。TreeNode()の中にTreeNode-TreePopの組み合わせを入れることで親子構造になります。
TreePop()は、ツリーが開いているときに、ツリーの終了をあらわす関数です。
TreeNode()が開くとtrueが帰ります。ifで検出して、開いているときにGUIを表示、最後にTreePop()を記述します。
ツリーが閉じているときは、記述不要です。

このサンプルでは、ツリーのなかに数値入力部品を配置しています。
入力系の部品は、変数に入力値を渡すため、Pythonでは一工夫が必要になります。
本実装では、list型変数を入力関数に渡しています。
InputFloat()、InputInt()は、それぞれ浮動小数点数、整数を入力します。サンプルでは、それぞれの値を受け渡しするためにfNum、nNum変数をlist型で初期化しています。
list型変数の最初の要素に値を入れます。

PushItemWidth()は、GUI部品の表示幅を設定します。設定しない場合、標準の表示幅になります。見た目が微妙になるため、表示幅を制御したほうがよいです。
PushItemWidth()は、PopItemWidth()と必ず組にしてください。

#LAYOUT
import vrmapi

nNum = [0]
fNum = [0.0]

def vrmevent(obj,ev,param):
    if ev == 'init':
        obj.SetEventFrame()
    elif ev == 'broadcast':
        dummy = 1
    elif ev == 'timer':
        dummy = 1
    elif ev == 'time':
        dummy = 1
    elif ev == 'after':
        dummy = 1
    elif ev == 'frame':
        global nNum
        global fNum
        vrmapi.ImGui().Begin("win1","Sample Window")

        if vrmapi.ImGui().TreeNode("tree1", "Tree-A"):
            vrmapi.ImGui().PushItemWidth(160.0)
            vrmapi.ImGui().InputFloat("f1", "浮動小数点数", fNum)
            vrmapi.ImGui().InputInt("n1", "整数", nNum)
            vrmapi.ImGui().PopItemWidth()
            vrmapi.ImGui().TreePop()

        vrmapi.ImGui().End()
    elif ev == 'keydown':
        dummy = 1
実行結果