新横浜駅「キュービックプラザ新横浜」のGWイベントに新幹線シミュレーターが登場します。詳しくは、 下記、キュービックプラザ新横浜のイベント情報をご参照ください。
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
VRMCLOUD Android 8.0対応について
VRMCLOUDのAndroid対応アプリについて、Google Playのポリシーにより次回更新からAndroid 8.0以上対応に変更となります。
現在、Android8対応版の開発テストを行っています。ハードウェアチェックなどが完了次第、公開する予定です。
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
GUIサンプル ボタン
βテストにご参加いただきまことにありがとうございます。
次はボタンのサンプルです。
ボタンは、クリックするとtrueを返します。ifでボタンが押されたことを検出します。
サンプルでは、ボタンが押されたことを記録するために、整数値を持つbtn変数をグローバル変数として用意しています。
frameイベントの最初にグローバル変数を使うことを宣言するため、global btnを記述します。
(記述しない場合、btnという名前のローカル変数になってしまいます。)
Begin()-End()の間に、Button()を記述します。ボタンは、入力をもつGUI部品のため、この部品だけのタグをつけます。サンプルでは、”b1″としています。
ifでボタンが押されたらbtn変数に1を代入します。
次にボタンが押されたことをあらわすメッセージを表示します。btn変数が1ならば、ボタンが押されたことになりますのでifで検出します。
ifでGUIの状態変化を検出、状態を記録する変数はグローバル変数にすることがポイントです。
#LAYOUT
import vrmapi
btn = 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 btn
vrmapi.ImGui().Begin("win1","Sample Window")
vrmapi.ImGui().Text("ボタンテスト")
vrmapi.ImGui().Text("btn変数の状態 =>"+str(btn))
if vrmapi.ImGui().Button("b1", "ボタンその1"):
btn = 1
if btn == 1:
vrmapi.ImGui().Text("ボタンをクリックした")
vrmapi.ImGui().End()
elif ev == 'keydown':
dummy = 1
GUIサンプル ウィンドウを開く
βテストにご参加いただきまことにありがとうございます。
ビルド50では、スクリプトからNXシステムに組み込まれているGUI=ImGuiを利用できるようになりました。
ImGuiの基本的な機能を利用できる関数を実装しています。
ImGuiは、イベント駆動で動作するWin32などのGUIと異なり、Direct3D、OpenGLなど3DAPIと親和性の高い、直接駆動が特徴です。
3D APIの描画シーケンスの1つとして、毎フレーム実行します。実行結果は関数の戻り値であらわされます。
ウィンドウを開く
最初のサンプルは、ウィンドウを生成するコードです。非常に簡単です。
Begin()とEnd()を実行するだけで、ウィンドウが生成されます。
Begin()とEnd()の間に、ウィンドウに表示するGUI部品を記述します。
毎フレーム実行するため、レイアウトスクリプトのinitイベントでSetEventFrame()を実行します。
frameイベントには、Begin()-End()とテスト用にウィンドウにテキストを表示するText()を記述します。
ImGuiで重要なことは、ウィンドウ、GUI部品を部品名で識別していることです。同じ名前の部品を使用すると入力できなくなります。
これを避けるため、タグを部品に設定します。タグをすべての部品で一意の名前にすることで、部品名の衝突を避けることができます。
(ImGuiを呼び出す前に内部でラベルとタグから部品名を生成しています。)
#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("tag_w","Sample Window")
vrmapi.ImGui().Text("テキスト表示サンプル")
vrmapi.ImGui().End()
elif ev == 'keydown':
dummy = 1