Skip to content

Commit b9193bb

Browse files
committed
Automatic merge of T1.5.1-687-gd279e384a and 18 pull requests
- Pull request #570 at c59c788: Experimental glTF 2.0 support with PBR lighting - Pull request #839 at d00beb9: First phase of https://blueprints.launchpad.net/or/+spec/additional-cruise-control-parameters - Pull request #865 at 67014b7: Dispatcher window improvements - Pull request #874 at f8dbeab: Dynamic brake controller refactoring - Pull request #875 at 43bf33e: Bug fix for https://bugs.launchpad.net/or/+bug/2036346 Player train switching doesn't work with 3D cabs - Pull request #876 at f92de76: docs: add source for documents previously on website to source Documentation folder - Pull request #878 at 25f5e06: Implement Polach Adhesion - Pull request #882 at d8a1c4d: Blueprint/train car operations UI window - Pull request #883 at edcc2dd: SwitchPanel disconnect/connect handling - Pull request #885 at c81447b: feat: Add notifications to Menu - Pull request #886 at ae66555: Scene viewer extension to TrackViewer - Pull request #887 at 4665bda: docs: Document projects, assemblies, namespaces - Pull request #888 at d7daf62: docs: Document player application model - Pull request #889 at 43341cf: No speed update - Pull request #892 at 1f5ba4c: Signal Function OPP_SIG_ID_TRAINPATH - Pull request #893 at bf8876b: Signal errors - Pull request #894 at 794fddf: Correct Decrease Colour - Pull request #896 at 5866028: First implementation of https://blueprints.launchpad.net/or/+spec/specific-sounds-for-ai-trains
20 parents 539be1f + d279e38 + c59c788 + d00beb9 + 67014b7 + f8dbeab + 43bf33e + f92de76 + 25f5e06 + d8a1c4d + edcc2dd + c81447b + ae66555 + 4665bda + d7daf62 + 43341cf + 1f5ba4c + bf8876b + 794fddf + 5866028 commit b9193bb

File tree

20 files changed

+526
-174
lines changed

20 files changed

+526
-174
lines changed

Source/Contrib/TrackViewer/SceneViewer.cs

Lines changed: 109 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
using Orts.Viewer3D.Processes;
4040
using System.Threading;
4141
using System.Threading.Tasks;
42+
using System.IO;
43+
using System.Globalization;
4244

4345
namespace ORTS.TrackViewer
4446
{
@@ -48,8 +50,9 @@ public class SceneViewer
4850

4951
public SceneWindow SceneWindow;
5052
public GameWindow SwapChainWindow;
51-
TrackViewer TrackViewer;
53+
public readonly TrackViewer TrackViewer;
5254
SwapChainRenderTarget SwapChain;
55+
internal StaticShape SelectedObject;
5356

5457
/// <summary>The command-line arguments</summary>
5558
private string[] CommandLineArgs;
@@ -100,15 +103,12 @@ public SceneViewer(TrackViewer trackViewer, string[] args)
100103
// Not "running" this Game, so manual init is needed
101104
Initialize();
102105
LoadContent();
103-
104-
Microsoft.Xna.Framework.Input.Mouse.WindowHandle = SwapChainWindow.Handle;
105106
}
106107

107108
/// <summary>
108109
/// Allows the game to perform any initialization it needs to before starting to run.
109110
/// This is where it can query for any required services and load any non-graphic
110-
/// relation ontent. Calling base.Initialize will enumerate through any components
111-
/// and initialize them as well.
111+
/// relation ontent.
112112
/// </summary>
113113
public void Initialize()
114114
{
@@ -130,15 +130,21 @@ public void LoadContent()
130130
/// <param name="gameTime">Provides a snapshot of timing values.</param>
131131
public void Update(GameTime gameTime)
132132
{
133-
SetCameraLocationStatus(TrackViewer.RenderProcess?.Viewer?.Camera?.CameraWorldLocation ?? new WorldLocation());
134-
}
133+
if (TrackViewer.RenderProcess?.Viewer == null)
134+
return;
135135

136-
/// <summary>
137-
/// This is called when the game should draw itself.
138-
/// </summary>
139-
/// <param name="gameTime">Provides a snapshot of timing values.</param>
140-
public void Draw(GameTime gameTime)
141-
{
136+
TrackViewer.RenderProcess.Viewer.EditorShapes.MouseCrosshairEnabled = true;
137+
138+
if (UserInput.IsMouseLeftButtonPressed && UserInput.ModifiersMaskShiftCtrlAlt(false, false, false))
139+
{
140+
if (PickByMouse(out SelectedObject))
141+
{
142+
TrackViewer.RenderProcess.Viewer.EditorShapes.SelectedObject = SelectedObject;
143+
FillSelectedObjectData();
144+
}
145+
}
146+
//SetCameraLocationStatus(TrackViewer.RenderProcess?.Viewer?.Camera?.CameraWorldLocation ?? new WorldLocation());
147+
FillCursorPositionStatus((TrackViewer.RenderProcess?.Viewer?.Camera as ViewerCamera)?.CursorPoint ?? new Vector3());
142148
}
143149

144150
public void EndDraw()
@@ -173,6 +179,15 @@ private void SetCameraLocationStatus(WorldLocation cameraLocation)
173179
"{0,3:F3} ", cameraLocation.Location.Z);
174180
}
175181

182+
private void FillCursorPositionStatus(Vector3 cursorPosition)
183+
{
184+
//SceneWindow.tileXZ.Text = string.Format(System.Globalization.CultureInfo.CurrentCulture,
185+
// "{0,-7} {1,-7}", cameraLocation.TileX, cameraLocation.TileZ);
186+
SceneWindow.LocationX.Text = string.Format(CultureInfo.InvariantCulture, "{0,3:F3} ", cursorPosition.X);
187+
SceneWindow.LocationY.Text = string.Format(CultureInfo.InvariantCulture, "{0,3:F3} ", cursorPosition.Y);
188+
SceneWindow.LocationZ.Text = string.Format(CultureInfo.InvariantCulture, "{0,3:F3} ", -cursorPosition.Z);
189+
}
190+
176191
public async Task SetCameraLocation()
177192
{
178193
var mouseLocation = TrackViewer.drawLabels.SetLocationMenuItem.CommandParameter as WorldLocation? ?? new WorldLocation();
@@ -195,6 +210,87 @@ public async Task SetCameraLocation()
195210
mouseLocation.Location.Y = elevatedLocation + 15;
196211
TrackViewer.RenderProcess.Viewer.ViewerCamera.SetLocation(mouseLocation);
197212
}
213+
214+
protected bool PickByMouse(out StaticShape pickedObject)
215+
{
216+
var viewer = TrackViewer.RenderProcess.Viewer;
217+
218+
if (viewer == null)
219+
{
220+
pickedObject = null;
221+
return false;
222+
}
223+
224+
var camera = viewer.Camera;
225+
226+
var direction = Vector3.Normalize(viewer.FarPoint - viewer.NearPoint);
227+
var pickRay = new Ray(viewer.NearPoint, direction);
228+
229+
pickedObject = null;
230+
var pickedDistance = float.MaxValue;
231+
foreach (var worldFile in viewer.World.Scenery.WorldFiles)
232+
{
233+
foreach (var sceneryObject in worldFile.sceneryObjects)
234+
{
235+
float? distance = null;
236+
237+
if (sceneryObject.BoundingBox is Orts.Viewer3D.BoundingBox boundingBox)
238+
{
239+
// Locate relative to the camera
240+
var dTileX = sceneryObject.Location.TileX - camera.TileX;
241+
var dTileZ = sceneryObject.Location.TileZ - camera.TileZ;
242+
var xnaDTileTranslation = sceneryObject.Location.XNAMatrix;
243+
xnaDTileTranslation.M41 += dTileX * 2048;
244+
xnaDTileTranslation.M43 -= dTileZ * 2048;
245+
246+
var min = Vector3.Transform(boundingBox.Min, xnaDTileTranslation);
247+
var max = Vector3.Transform(boundingBox.Max, xnaDTileTranslation);
248+
249+
var xnabb = new Microsoft.Xna.Framework.BoundingBox(min, max);
250+
distance = pickRay.Intersects(xnabb);
251+
}
252+
else
253+
{
254+
var radius = 10f;
255+
var boundingSphere = new BoundingSphere(camera.XnaLocation(sceneryObject.Location.WorldLocation), radius);
256+
distance = pickRay.Intersects(boundingSphere);
257+
}
258+
259+
if (distance != null)
260+
{
261+
if (distance < pickedDistance)
262+
{
263+
pickedDistance = distance.Value;
264+
pickedObject = sceneryObject;
265+
}
266+
}
267+
}
268+
}
269+
return pickedObject != null;
270+
}
271+
272+
void FillSelectedObjectData()
273+
{
274+
SceneWindow.Filename.Text = SelectedObject != null ? System.IO.Path.GetFileName(SelectedObject.SharedShape.FilePath) : "";
275+
SceneWindow.TileX.Text = SelectedObject?.Location.TileX.ToString(CultureInfo.InvariantCulture).Replace(",", "");
276+
SceneWindow.TileZ.Text = SelectedObject?.Location.TileZ.ToString(CultureInfo.InvariantCulture).Replace(",", "");
277+
SceneWindow.PosX.Text = SelectedObject?.Location.Location.X.ToString("N3", CultureInfo.InvariantCulture).Replace(",", "");
278+
SceneWindow.PosY.Text = SelectedObject?.Location.Location.Y.ToString("N3", CultureInfo.InvariantCulture).Replace(",", "");
279+
SceneWindow.PosZ.Text = SelectedObject?.Location.Location.Z.ToString("N3", CultureInfo.InvariantCulture).Replace(",", "");
280+
if (SelectedObject?.Location.XNAMatrix.Decompose(out var _, out var q, out var _) ?? false)
281+
{
282+
var mag = Math.Sqrt(q.W * q.W + q.Y * q.Y);
283+
var w = q.W / mag;
284+
var ang = 2.0 * Math.Acos(w) / Math.PI * 180;
285+
SceneWindow.RotY.Text = ang.ToString("N3", CultureInfo.InvariantCulture).Replace(",", "");
286+
}
287+
else
288+
{
289+
SceneWindow.RotY.Text = "";
290+
}
291+
SceneWindow.Uid.Text = SelectedObject.Uid.ToString(CultureInfo.InvariantCulture).Replace(",", "");
292+
}
293+
198294
}
199295

200296
public class SceneViewerHwndHost : HwndHost
@@ -225,24 +321,6 @@ protected override HandleRef BuildWindowCore(HandleRef hwndParent)
225321

226322
protected override void DestroyWindowCore(HandleRef hwnd)
227323
{
228-
229-
}
230-
}
231-
232-
public class SceneViewerVisualHost : UIElement
233-
{
234-
System.Windows.Media.Visual Visual;
235-
236-
public SceneViewerVisualHost(GameWindow gameWindow)
237-
{
238-
Visual = HwndSource.FromHwnd(gameWindow.Handle).RootVisual;
239-
}
240-
241-
protected override int VisualChildrenCount { get { return Visual != null ? 1 : 0; } }
242-
243-
protected override System.Windows.Media.Visual GetVisualChild(int index)
244-
{
245-
return Visual;
246324
}
247325
}
248326
}

Source/Contrib/TrackViewer/TrackViewer.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,6 @@ protected override void Update(GameTime gameTime)
557557
protected override void Draw(GameTime gameTime)
558558
{
559559
graphics.GraphicsDevice.SetRenderTarget(null);
560-
SceneViewer?.Draw(gameTime);
561560

562561
// Even if there is nothing new to draw for main window, we might still need to draw for the shadow textures.
563562
if (DrawTrackDB != null && Properties.Settings.Default.showInset)
@@ -1253,4 +1252,17 @@ class GameStateStandBy : GameState
12531252
{
12541253
public GameStateStandBy() { }
12551254
}
1255+
1256+
class GameStateSceneViewer3D : GameStateViewer3D
1257+
{
1258+
public GameStateSceneViewer3D(Viewer viewer)
1259+
: base(viewer) { }
1260+
1261+
public override void Update(RenderFrame frame, double totalRealSeconds)
1262+
{
1263+
base.Update(frame, totalRealSeconds);
1264+
1265+
1266+
}
1267+
}
12561268
}

Source/Contrib/TrackViewer/UserInterface/SceneWindow.xaml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,51 @@
112112
<TextBlock Name="statusAdditional" ToolTip="Any other relevant information. Make your choice via Statusbar menu"/>
113113
</StatusBarItem>
114114
</StatusBar>
115+
<Border BorderThickness="2">
116+
<StackPanel Orientation="Vertical" Width="150">
117+
<TextBox FontWeight="Bold" Name="Filename"/>
118+
<DockPanel>
119+
<TextBlock Text="UID: " PreviewTextInput="UintValidationTextBox"/>
120+
<TextBlock Name="Uid"/>
121+
</DockPanel>
122+
<Grid>
123+
<Grid.ColumnDefinitions>
124+
<ColumnDefinition Width="Auto"/>
125+
<ColumnDefinition Width="*"/>
126+
<ColumnDefinition Width="Auto"/>
127+
<ColumnDefinition Width="*"/>
128+
</Grid.ColumnDefinitions>
129+
<TextBlock Grid.Column="0" Text="Tile X: " />
130+
<TextBox Grid.Column="1" Name="TileX" PreviewTextInput="IntValidationTextBox"></TextBox>
131+
<TextBlock Grid.Column="2" Text=" Z: " />
132+
<TextBox Grid.Column="3" Name="TileZ" PreviewTextInput="IntValidationTextBox"></TextBox>
133+
</Grid>
134+
<Grid>
135+
<Grid.RowDefinitions>
136+
<RowDefinition Height="Auto" />
137+
<RowDefinition Height="Auto" />
138+
<RowDefinition Height="Auto" />
139+
<RowDefinition Height="Auto" />
140+
</Grid.RowDefinitions>
141+
<Grid.ColumnDefinitions>
142+
<ColumnDefinition Width="Auto" />
143+
<ColumnDefinition Width="*" />
144+
<ColumnDefinition Width="*" />
145+
</Grid.ColumnDefinitions>
146+
<TextBlock Grid.Row="0" Grid.Column="1" Text="Position" HorizontalAlignment="Center"/>
147+
<TextBlock Grid.Row="0" Grid.Column="2" Text="Rotation" HorizontalAlignment="Center"/>
148+
<TextBlock Grid.Row="1" Text="X: "/>
149+
<TextBlock Grid.Row="2" Text="Y: "/>
150+
<TextBlock Grid.Row="3" Text="Z: "/>
151+
<TextBox Grid.Row="1" Grid.Column="1" x:Name="PosX" PreviewTextInput="FloatValidationTextBox"/>
152+
<TextBox Grid.Row="2" Grid.Column="1" x:Name="PosY" PreviewTextInput="FloatValidationTextBox"/>
153+
<TextBox Grid.Row="3" Grid.Column="1" x:Name="PosZ" PreviewTextInput="FloatValidationTextBox"/>
154+
<TextBox Grid.Row="1" Grid.Column="2" x:Name="RotX" PreviewTextInput="FloatValidationTextBox"/>
155+
<TextBox Grid.Row="2" Grid.Column="2" x:Name="RotY" PreviewTextInput="FloatValidationTextBox"/>
156+
<TextBox Grid.Row="3" Grid.Column="2" x:Name="RotZ" PreviewTextInput="FloatValidationTextBox"/>
157+
</Grid>
158+
</StackPanel>
159+
</Border>
115160
<Grid DockPanel.Dock="Bottom" x:Name="GraphicsHostElement" />
116161
</DockPanel>
117162
</Window>

Source/Contrib/TrackViewer/UserInterface/SceneWindow.xaml.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,20 @@ protected override void OnClosing(CancelEventArgs e)
3636
e.Cancel = true;
3737
Hide();
3838
}
39+
40+
private void IntValidationTextBox(object sender, TextCompositionEventArgs e)
41+
{
42+
e.Handled = int.TryParse(e.Text, out var _);
43+
}
44+
45+
private void UintValidationTextBox(object sender, TextCompositionEventArgs e)
46+
{
47+
e.Handled = uint.TryParse(e.Text, out var _);
48+
}
49+
50+
private void FloatValidationTextBox(object sender, TextCompositionEventArgs e)
51+
{
52+
e.Handled = float.TryParse(e.Text, out var _);
53+
}
3954
}
4055
}

0 commit comments

Comments
 (0)