diff --git a/BlocklyAtsGui/Host/PlatformFunction.cs b/BlocklyAtsGui/Host/PlatformFunction.cs index 5364f92..e16d87b 100644 --- a/BlocklyAtsGui/Host/PlatformFunction.cs +++ b/BlocklyAtsGui/Host/PlatformFunction.cs @@ -14,9 +14,6 @@ namespace BlocklyAts.Host { static class PlatformFunction { public static readonly string AppDir = Path.GetDirectoryName(Application.ExecutablePath); - - public static readonly string AppName = Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName); - static readonly string featureControlRegKey = @"Software\Microsoft\Internet Explorer\Main\FeatureControl\"; public static bool IsMono { get; } = Type.GetType("Mono.Runtime") != null; @@ -66,6 +63,7 @@ public static void SetWebBrowserFeatures() { if (IsMono) return; // don't change the registry if running in-proc inside Visual Studio if (LicenseManager.UsageMode != LicenseUsageMode.Runtime) return; + var AppName = Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName); Registry.CurrentUser.CreateSubKey(featureControlRegKey + "FEATURE_BROWSER_EMULATION", true) .SetValue(AppName, GetBrowserEmulationMode(), RegistryValueKind.DWord); @@ -88,6 +86,7 @@ public static void UnsetWebBrowserFeatures() { // don't change the registry if running in-proc inside Visual Studio if (LicenseManager.UsageMode != LicenseUsageMode.Runtime) return; + var AppName = Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName); Registry.CurrentUser.OpenSubKey(featureControlRegKey + "FEATURE_BROWSER_EMULATION", true) ?.DeleteValue(AppName); diff --git a/BlocklyAtsGui/Properties/AssemblyInfo.cs b/BlocklyAtsGui/Properties/AssemblyInfo.cs index 178c8fe..ad97792 100644 --- a/BlocklyAtsGui/Properties/AssemblyInfo.cs +++ b/BlocklyAtsGui/Properties/AssemblyInfo.cs @@ -32,4 +32,4 @@ // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 // 方法是按如下所示使用“*”: : // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.1.0.1")] +[assembly: AssemblyVersion("1.1.0.2")] diff --git a/BlocklyAtsGui/UserInterface/FormDebug.Designer.cs b/BlocklyAtsGui/UserInterface/FormDebug.Designer.cs index 6da3653..eec6307 100644 --- a/BlocklyAtsGui/UserInterface/FormDebug.Designer.cs +++ b/BlocklyAtsGui/UserInterface/FormDebug.Designer.cs @@ -24,9 +24,10 @@ protected override void Dispose(bool disposing) { /// private void InitializeComponent() { this.flpMain = new System.Windows.Forms.FlowLayoutPanel(); - this.pnlMain = new System.Windows.Forms.Panel(); this.rbBve456 = new System.Windows.Forms.RadioButton(); this.rbOpenBve = new System.Windows.Forms.RadioButton(); + this.pnlMain = new System.Windows.Forms.Panel(); + this.lblCursorPos = new System.Windows.Forms.Label(); this.flpMain.SuspendLayout(); this.SuspendLayout(); // @@ -36,6 +37,7 @@ private void InitializeComponent() { this.flpMain.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.flpMain.Controls.Add(this.rbBve456); this.flpMain.Controls.Add(this.rbOpenBve); + this.flpMain.Controls.Add(this.lblCursorPos); this.flpMain.Dock = System.Windows.Forms.DockStyle.Top; this.flpMain.Location = new System.Drawing.Point(0, 0); this.flpMain.Name = "flpMain"; @@ -43,14 +45,6 @@ private void InitializeComponent() { this.flpMain.Size = new System.Drawing.Size(784, 42); this.flpMain.TabIndex = 2; // - // pnlMain - // - this.pnlMain.Dock = System.Windows.Forms.DockStyle.Fill; - this.pnlMain.Location = new System.Drawing.Point(0, 42); - this.pnlMain.Name = "pnlMain"; - this.pnlMain.Size = new System.Drawing.Size(784, 419); - this.pnlMain.TabIndex = 3; - // // rbBve456 // this.rbBve456.AutoSize = true; @@ -76,6 +70,25 @@ private void InitializeComponent() { this.rbOpenBve.UseVisualStyleBackColor = true; this.rbOpenBve.CheckedChanged += new System.EventHandler(this.rbCheckedChanged); // + // pnlMain + // + this.pnlMain.Dock = System.Windows.Forms.DockStyle.Fill; + this.pnlMain.Location = new System.Drawing.Point(0, 42); + this.pnlMain.Name = "pnlMain"; + this.pnlMain.Size = new System.Drawing.Size(784, 419); + this.pnlMain.TabIndex = 3; + // + // lblCursorPos + // + this.lblCursorPos.AutoSize = true; + this.lblCursorPos.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.lblCursorPos.Location = new System.Drawing.Point(204, 10); + this.lblCursorPos.Margin = new System.Windows.Forms.Padding(40, 0, 3, 0); + this.lblCursorPos.Name = "lblCursorPos"; + this.lblCursorPos.Size = new System.Drawing.Size(120, 16); + this.lblCursorPos.TabIndex = 2; + this.lblCursorPos.Text = "Row: 0; Col: 0"; + // // FormDebug // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); @@ -97,5 +110,6 @@ private void InitializeComponent() { private System.Windows.Forms.Panel pnlMain; private System.Windows.Forms.RadioButton rbBve456; private System.Windows.Forms.RadioButton rbOpenBve; + private System.Windows.Forms.Label lblCursorPos; } } \ No newline at end of file diff --git a/BlocklyAtsGui/UserInterface/FormDebug.cs b/BlocklyAtsGui/UserInterface/FormDebug.cs index b685642..0d259e7 100644 --- a/BlocklyAtsGui/UserInterface/FormDebug.cs +++ b/BlocklyAtsGui/UserInterface/FormDebug.cs @@ -60,6 +60,15 @@ private void ResetTextbox(string text) { tbCode.Zoom = 100; tbCode.Language = FastColoredTextBoxNS.Language.CSharp; tbCode.Text = text; + tbCode.SelectionChanged += (object sender, EventArgs e) => { + var selection = tbCode.Selection.Start; + if (selection == null) { + selection = new FastColoredTextBoxNS.Place(0, 0); + } + lblCursorPos.Text = string.Format("Row: {0}; Col: {1}", + selection.iLine + 1, selection.iChar + 1); + }; + lblCursorPos.Text = "Row: 0; Col: 0"; pnlMain.Controls.Add(tbCode); ((ISupportInitialize)(tbCode)).EndInit(); } else { @@ -75,6 +84,7 @@ private void ResetTextbox(string text) { fallbackTbCode.Dock = DockStyle.Fill; fallbackTbCode.TabIndex = 2; fallbackTbCode.Text = text; + lblCursorPos.Text = ""; pnlMain.Controls.Add(fallbackTbCode); } ResumeLayout(false); diff --git a/BlocklyAtsGui/Workspace/CompilerFunction.cs b/BlocklyAtsGui/Workspace/CompilerFunction.cs index 3acc88b..25199ee 100644 --- a/BlocklyAtsGui/Workspace/CompilerFunction.cs +++ b/BlocklyAtsGui/Workspace/CompilerFunction.cs @@ -99,21 +99,14 @@ public static void Compile(string script, string outputPath, Platform platform, const string defaultModuleName = "AtsCallConverter00000000000000000000000000000000"; var randomModuleName = "AtsCallConverter" + Guid.NewGuid().ToString("N"); // Prevent module name conflicts - var tempOutputPath = Path.Combine(Path.GetDirectoryName(outputPath), + var tempOutputPath = Path.Combine(Path.GetDirectoryName(outputPath), "BlocklyAtsGenerated-" + Guid.NewGuid() + ".dll"); + var modifiedProxyDllPath = Path.Combine(Path.GetDirectoryName(outputPath), randomModuleName + ".dll"); var sourceCode = CombineCode(script, platform); var settings = new Dictionary() { { "CompilerVersion", "v4.0" } }; - CSharpCodeProvider codeProvider = new CSharpCodeProvider(settings); - CompilerParameters parameters = new CompilerParameters() { - IncludeDebugInformation = includePDB, - GenerateExecutable = false, - OutputAssembly = tempOutputPath, - }; - if (!includePDB) parameters.CompilerOptions += "/optimize"; - string[] commonReferences = new string[] { "mscorlib.dll", "System.Core.dll", @@ -121,72 +114,81 @@ public static void Compile(string script, string outputPath, Platform platform, "Microsoft.CSharp.dll", "System.Windows.Forms.dll" }; - foreach (string a in commonReferences) parameters.ReferencedAssemblies.Add(a); - string modifiedProxyDllPath = null; - if (platform == Platform.OpenBve) { - parameters.ReferencedAssemblies.Add(Path.Combine(PlatformFunction.AppDir, "lib", "OpenBveApi.dll")); - } else if (platform == Platform.WinDll32 || platform == Platform.WinDll64) { - var boilerplateFile = Path.Combine( - PlatformFunction.AppDir, - "lib", - platform == Platform.WinDll32 ? "AtsCallConverter_x86.dll" : "AtsCallConverter_x64.dll" - ); - modifiedProxyDllPath = Path.Combine(Path.GetDirectoryName(outputPath), randomModuleName + ".dll"); - byte[] srcBytes = File.ReadAllBytes(boilerplateFile); - byte[] classNameBytes = Encoding.ASCII.GetBytes(randomModuleName); - - // You need to use different module names for each plugin. - // Otherwise, the type references will mess up when multiple plugins are loaded by DetailManager. - ReplaceBytes(ref srcBytes, Encoding.ASCII.GetBytes(defaultModuleName), - Encoding.ASCII.GetBytes(randomModuleName)); - ReplaceBytes(ref srcBytes, Encoding.Unicode.GetBytes(defaultModuleName), - Encoding.Unicode.GetBytes(randomModuleName)); - File.WriteAllBytes(modifiedProxyDllPath, srcBytes); - parameters.ReferencedAssemblies.Add(modifiedProxyDllPath); - } - CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, sourceCode); - if (results.Errors.HasErrors) { - if (modifiedProxyDllPath != null) File.Delete(modifiedProxyDllPath); - if (tempOutputPath != null) File.Delete(tempOutputPath); - throw new CompileException(results.Errors); - } + try { + CSharpCodeProvider codeProvider = new CSharpCodeProvider(settings); + CompilerParameters parameters = new CompilerParameters() { + IncludeDebugInformation = includePDB, + GenerateExecutable = false, + OutputAssembly = tempOutputPath, + }; + if (!includePDB) parameters.CompilerOptions += "/optimize"; + + foreach (string a in commonReferences) parameters.ReferencedAssemblies.Add(a); + if (platform == Platform.OpenBve) { + parameters.ReferencedAssemblies.Add(Path.Combine(PlatformFunction.AppDir, "lib", "OpenBveApi.dll")); + } else if (platform == Platform.WinDll32 || platform == Platform.WinDll64) { + var boilerplateFile = Path.Combine( + PlatformFunction.AppDir, + "lib", + platform == Platform.WinDll32 ? "AtsCallConverter_x86.dll" : "AtsCallConverter_x64.dll" + ); + byte[] srcBytes = File.ReadAllBytes(boilerplateFile); + byte[] classNameBytes = Encoding.ASCII.GetBytes(randomModuleName); + + // You need to use different module names for each plugin. + // Otherwise, the type references will mess up when multiple plugins are loaded by DetailManager. + ReplaceBytes(ref srcBytes, Encoding.ASCII.GetBytes(defaultModuleName), + Encoding.ASCII.GetBytes(randomModuleName)); + ReplaceBytes(ref srcBytes, Encoding.Unicode.GetBytes(defaultModuleName), + Encoding.Unicode.GetBytes(randomModuleName)); + File.WriteAllBytes(modifiedProxyDllPath, srcBytes); + parameters.ReferencedAssemblies.Add(modifiedProxyDllPath); + } - if (File.Exists(outputPath)) File.Delete(outputPath); - if (platform == Platform.OpenBve) { - File.Copy(tempOutputPath, outputPath); - var targetPdbFile = Path.ChangeExtension(outputPath, ".pdb"); - if (File.Exists(targetPdbFile)) File.Delete(targetPdbFile); - File.Move(Path.ChangeExtension(tempOutputPath, ".pdb"), targetPdbFile); - } else if (platform == Platform.WinDll32 || platform == Platform.WinDll64) { - var programData = new FileStream(tempOutputPath, FileMode.Open, FileAccess.Read); - var proxyStream = new FileStream(modifiedProxyDllPath, FileMode.Open, FileAccess.Read); - var outStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write); - - // Write Identifier and PE length to DOS stub - byte[] identifier = Encoding.UTF8.GetBytes("BATSNET1"); - proxyStream.CopySectionTo(outStream, 0x6C - identifier.Length); - outStream.Write(identifier, 0, identifier.Length); - outStream.Write(BitConverter.GetBytes(proxyStream.Length), 0, 4); - outStream.Write(BitConverter.GetBytes(programData.Length), 0, 4); - proxyStream.Seek(8 + identifier.Length, SeekOrigin.Current); - proxyStream.CopyTo(outStream); - proxyStream.Close(); - - programData.CopyTo(outStream); - programData.Close(); - if (includePDB) { - var pdbFilePath = Path.ChangeExtension(tempOutputPath, ".pdb"); - var pdbStream = new FileStream(pdbFilePath, FileMode.Open, FileAccess.Read); - pdbStream.CopyTo(outStream); - pdbStream.Close(); - File.Delete(pdbFilePath); + CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, sourceCode); + if (results.Errors.HasErrors) { + throw new CompileException(results.Errors); } - outStream.Close(); - } - if (modifiedProxyDllPath != null) File.Delete(modifiedProxyDllPath); - if (tempOutputPath != null) File.Delete(tempOutputPath); + if (File.Exists(outputPath)) File.Delete(outputPath); + if (platform == Platform.OpenBve) { + File.Copy(tempOutputPath, outputPath); + if (includePDB) { + var targetPdbFile = Path.ChangeExtension(outputPath, ".pdb"); + if (File.Exists(targetPdbFile)) File.Delete(targetPdbFile); + File.Move(Path.ChangeExtension(tempOutputPath, ".pdb"), targetPdbFile); + } + } else if (platform == Platform.WinDll32 || platform == Platform.WinDll64) { + var programData = new FileStream(tempOutputPath, FileMode.Open, FileAccess.Read); + var proxyStream = new FileStream(modifiedProxyDllPath, FileMode.Open, FileAccess.Read); + var outStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write); + + // Write Identifier and PE length to DOS stub + byte[] identifier = Encoding.UTF8.GetBytes("BATSNET1"); + proxyStream.CopySectionTo(outStream, 0x6C - identifier.Length); + outStream.Write(identifier, 0, identifier.Length); + outStream.Write(BitConverter.GetBytes(proxyStream.Length), 0, 4); + outStream.Write(BitConverter.GetBytes(programData.Length), 0, 4); + proxyStream.Seek(8 + identifier.Length, SeekOrigin.Current); + proxyStream.CopyTo(outStream); + proxyStream.Close(); + + programData.CopyTo(outStream); + programData.Close(); + if (includePDB) { + var pdbFilePath = Path.ChangeExtension(tempOutputPath, ".pdb"); + var pdbStream = new FileStream(pdbFilePath, FileMode.Open, FileAccess.Read); + pdbStream.CopyTo(outStream); + pdbStream.Close(); + File.Delete(pdbFilePath); + } + outStream.Close(); + } + } finally { + if (modifiedProxyDllPath != null) File.Delete(modifiedProxyDllPath); + if (tempOutputPath != null) File.Delete(tempOutputPath); + } } } } diff --git a/BlocklyAtsGui/Workspace/SaveState.cs b/BlocklyAtsGui/Workspace/SaveState.cs index d643aaf..315f1c5 100644 --- a/BlocklyAtsGui/Workspace/SaveState.cs +++ b/BlocklyAtsGui/Workspace/SaveState.cs @@ -162,7 +162,11 @@ private string SelectDefaultCompilePath(string compilePath, string suffix) { Path.GetFileNameWithoutExtension(SaveFilePath) + suffix ); } else { - return compilePath; + if (Path.IsPathRooted(compilePath)) { + return compilePath; + } else { + return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(SaveFilePath), compilePath)); + } } } diff --git a/www/index.html b/www/index.html index 833082b..a4f0934 100644 --- a/www/index.html +++ b/www/index.html @@ -531,7 +531,7 @@ - + diff --git a/www/js/bats_code.js b/www/js/bats_code.js index d9a77ca..35b150c 100644 --- a/www/js/bats_code.js +++ b/www/js/bats_code.js @@ -137,6 +137,8 @@ function batsInit(toolboxNode) { bve_hat_set_beacon: 1, bve_hat_load: 1, bve_hat_dispose: 1, + bve_hat_door_change_any: 1, + bve_hat_perform_ai: 1 }, }); workspace.setTheme(themeWithHat); diff --git a/www/js/blocks_bve.js b/www/js/blocks_bve.js index f69f4a2..7b3acb9 100644 --- a/www/js/blocks_bve.js +++ b/www/js/blocks_bve.js @@ -622,9 +622,24 @@ Blockly.defineBlocksWithJsonArray([ output: "Number", }, { - type: "obve_destination", + type: "obve_vehicle_state", style: "openbve_blocks", - message0: "%{BKY_OBVE_DESTINATION}", + message0: "%{BKY_BVE_VEHICLE_STATE}", + args0: [ + { + type: "field_dropdown", + name: "FIELD_SEL", + options: [ + ["%{BKY_OBVE_VSTATE_RADIUS}", "Radius"], + ["%{BKY_OBVE_VSTATE_CANT}", "Cant"], + ["%{BKY_OBVE_VSTATE_PITCH}", "Pitch"], + /* ["%{BKY_OBVE_VSTATE_ADHESION}", "Adhesion"], + ["%{BKY_OBVE_VSTATE_RAININTENSITY}", "RainIntensity"], */ + ["%{BKY_OBVE_STATE_CAMERAVIEWMODE}", "CameraViewMode"], + ["%{BKY_OBVE_STATE_DESTINATION}", "Destination"], + ], + }, + ], output: "Number", }, { diff --git a/www/js/csharp_generator_bve.js b/www/js/csharp_generator_bve.js index 99e8926..ef6efe8 100644 --- a/www/js/csharp_generator_bve.js +++ b/www/js/csharp_generator_bve.js @@ -149,7 +149,7 @@ function batsExportCSharp(workspace) { code += indentString(Blockly.CSharp.blockToCode(block, true).trim(), 4, true); if (block.type == "bve_hat_load" && !allHats.includes("bve_hat_perform_ai")) { - code += "_c.LProp.AISupport = AISupport.Basic;\n"; + code += "\n _c.LProp.AISupport = AISupport.Basic;\n"; } code += "\n }\n\n"; @@ -159,7 +159,11 @@ function batsExportCSharp(workspace) { } code += "\n"; for (var i = 0, hatName; hatName = allHats[i]; i++) { - code += " " + Blockly.CSharp[hatName]().trim() + " }\n"; + code += " " + Blockly.CSharp[hatName]().trim(); + if (hatName == "bve_hat_load" && !allHats.includes("bve_hat_perform_ai")) { + code += " _c.LProp.AISupport = AISupport.Basic;"; + } + code += " }\n"; } code = Blockly.CSharp.finish(code); @@ -367,8 +371,13 @@ Blockly.CSharp.obve_next_station=function(block){ return [func + "." + block.getFieldValue("FIELD"), Blockly.CSharp.ORDER_MEMBER]; } } -Blockly.CSharp.obve_destination=function(block){ - return ["_c.EData.Destination", Blockly.CSharp.ORDER_MEMBER]; +Blockly.CSharp.obve_vehicle_state=function(block){ + var field = block.getFieldValue("FIELD_SEL"); + if (field == "CameraViewMode" || field == "Destination") { + return ["_c.EData." + field, Blockly.CSharp.ORDER_MEMBER]; + } else { + return ["_c.EData.Vehicle." + field, Blockly.CSharp.ORDER_MEMBER]; + } } Blockly.CSharp.obve_langcode=function(block){ return ["_c.EData.CurrentLanguageCode", Blockly.CSharp.ORDER_MEMBER]; diff --git a/www/js/msg_bats/en.js b/www/js/msg_bats/en.js index de20045..b6ac585 100644 --- a/www/js/msg_bats/en.js +++ b/www/js/msg_bats/en.js @@ -101,7 +101,13 @@ Blockly.Msg["OBVE_NEXTSTA_STOPTIME"]="stop time/s"; Blockly.Msg["OBVE_NEXTSTA_OPENLEFT"]="open left door? (0/1)"; Blockly.Msg["OBVE_NEXTSTA_OPENRIGHT"]="open right door? (0/1)"; Blockly.Msg["OBVE_NEXTSTA_FORCESTOP"]="force red signal? (0/1)"; -Blockly.Msg["OBVE_DESTINATION"]="train destination num"; +Blockly.Msg["OBVE_VSTATE_RADIUS"]="curve radius"; +Blockly.Msg["OBVE_VSTATE_CANT"]="curve cant"; +Blockly.Msg["OBVE_VSTATE_PITCH"]="pitch"; +Blockly.Msg["OBVE_VSTATE_ADHESION"]="adhesion"; +Blockly.Msg["OBVE_VSTATE_RAININTENSITY"]="rain intensity"; +Blockly.Msg["OBVE_STATE_CAMERAVIEWMODE"]="camera view mode"; +Blockly.Msg["OBVE_STATE_DESTINATION"]="destination code"; Blockly.Msg["OBVE_LANGCODE"]="language code name"; Blockly.Msg["OBVE_GET_DOOR"]="%1 door(s) opening?"; Blockly.Msg["OBVE_DOOR_LEFT"]="left"; diff --git a/www/js/msg_bats/ja.js b/www/js/msg_bats/ja.js index f25e94c..29c8851 100644 --- a/www/js/msg_bats/ja.js +++ b/www/js/msg_bats/ja.js @@ -101,7 +101,13 @@ Blockly.Msg["OBVE_NEXTSTA_STOPTIME"]="停止時間/s"; Blockly.Msg["OBVE_NEXTSTA_OPENLEFT"]="左のドアを開けますか? (0/1)"; Blockly.Msg["OBVE_NEXTSTA_OPENRIGHT"]="右のドアを開けますか? (0/1)"; Blockly.Msg["OBVE_NEXTSTA_FORCESTOP"]="出発停止? (0/1)"; -Blockly.Msg["OBVE_DESTINATION"]="行先コード"; +Blockly.Msg["OBVE_VSTATE_RADIUS"]="曲線半径"; +Blockly.Msg["OBVE_VSTATE_CANT"]="曲線カント"; +Blockly.Msg["OBVE_VSTATE_PITCH"]="勾配"; +Blockly.Msg["OBVE_VSTATE_ADHESION"]="粘着特性"; +Blockly.Msg["OBVE_VSTATE_RAININTENSITY"]="雨強度"; +Blockly.Msg["OBVE_STATE_CAMERAVIEWMODE"]="ビューモード"; +Blockly.Msg["OBVE_STATE_DESTINATION"]="行先コード"; Blockly.Msg["OBVE_LANGCODE"]="言語コード名"; Blockly.Msg["OBVE_GET_DOOR"]="%1 のドアが開いたか?"; Blockly.Msg["OBVE_DOOR_LEFT"]="左"; diff --git a/www/js/msg_bats/zh-hans.js b/www/js/msg_bats/zh-hans.js index 8eaa1ea..09bf402 100644 --- a/www/js/msg_bats/zh-hans.js +++ b/www/js/msg_bats/zh-hans.js @@ -101,7 +101,13 @@ Blockly.Msg["OBVE_NEXTSTA_STOPTIME"]="停车时间/s"; Blockly.Msg["OBVE_NEXTSTA_OPENLEFT"]="开左门? (0/1)"; Blockly.Msg["OBVE_NEXTSTA_OPENRIGHT"]="开右门? (0/1)"; Blockly.Msg["OBVE_NEXTSTA_FORCESTOP"]="开点前出站信号红灯? (0/1)"; -Blockly.Msg["OBVE_DESTINATION"]="终点站编号"; +Blockly.Msg["OBVE_VSTATE_RADIUS"]="曲线半径"; +Blockly.Msg["OBVE_VSTATE_CANT"]="曲线超高"; +Blockly.Msg["OBVE_VSTATE_PITCH"]="坡度"; +Blockly.Msg["OBVE_VSTATE_ADHESION"]="粘着特性"; +Blockly.Msg["OBVE_VSTATE_RAININTENSITY"]="雨强度"; +Blockly.Msg["OBVE_STATE_CAMERAVIEWMODE"]="视角模式"; +Blockly.Msg["OBVE_STATE_DESTINATION"]="终点站编号"; Blockly.Msg["OBVE_LANGCODE"]="语言编码名称"; Blockly.Msg["OBVE_GET_DOOR"]="%1 车门是否打开?"; Blockly.Msg["OBVE_DOOR_LEFT"]="左侧";