Skip to content

Commit be34497

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 f9aa2ad: 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 82fde3f: 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 56bd084 + d279e38 + c59c788 + d00beb9 + 67014b7 + f8dbeab + 43bf33e + f92de76 + f9aa2ad + d8a1c4d + edcc2dd + c81447b + 82fde3f + 4665bda + d7daf62 + 43341cf + 1f5ba4c + bf8876b + 794fddf + 5866028 commit be34497

File tree

8 files changed

+284
-214
lines changed

8 files changed

+284
-214
lines changed

Source/Contrib/TrackViewer/SceneViewer.cs

Lines changed: 68 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
using System.Threading.Tasks;
4242
using System.IO;
4343
using System.Globalization;
44+
using ORTS.Common.Input;
4445

4546
namespace ORTS.TrackViewer
4647
{
@@ -53,6 +54,9 @@ public class SceneViewer
5354
public readonly TrackViewer TrackViewer;
5455
SwapChainRenderTarget SwapChain;
5556
internal StaticShape SelectedObject;
57+
internal Orts.Formats.Msts.WorldObject SelectedWorldObject;
58+
Viewer Viewer;
59+
ViewerCamera Camera;
5660

5761
/// <summary>The command-line arguments</summary>
5862
private string[] CommandLineArgs;
@@ -88,7 +92,6 @@ public SceneViewer(TrackViewer trackViewer, string[] args)
8892
RenderFrame.FinalRenderTarget = SwapChain;
8993

9094
SceneWindow = new SceneWindow(new SceneViewerHwndHost(SwapChainWindow));
91-
//SceneWindow = new SceneWindow(new SceneViewerVisualHost(GameWindow));
9295

9396
// The primary window activation events should not affect RunActivity
9497
TrackViewer.Activated -= TrackViewer.ActivateRunActivity;
@@ -105,6 +108,8 @@ public SceneViewer(TrackViewer trackViewer, string[] args)
105108
LoadContent();
106109
}
107110

111+
public SceneViewer() { }
112+
108113
/// <summary>
109114
/// Allows the game to perform any initialization it needs to before starting to run.
110115
/// This is where it can query for any required services and load any non-graphic
@@ -130,21 +135,48 @@ public void LoadContent()
130135
/// <param name="gameTime">Provides a snapshot of timing values.</param>
131136
public void Update(GameTime gameTime)
132137
{
133-
if (TrackViewer.RenderProcess?.Viewer == null)
138+
Viewer = Viewer ?? TrackViewer.RenderProcess?.Viewer;
139+
if (Viewer == null)
134140
return;
141+
Camera = Camera ?? Viewer.ViewerCamera;
135142

136-
TrackViewer.RenderProcess.Viewer.EditorShapes.MouseCrosshairEnabled = true;
143+
Viewer.EditorShapes.MouseCrosshairEnabled = true;
137144

138-
if (UserInput.IsMouseLeftButtonPressed && UserInput.ModifiersMaskShiftCtrlAlt(false, false, false))
145+
if (UserInput.IsMouseLeftButtonPressed && UserInput.ModifiersMaskShiftCtrlAlt(false, false, false)
146+
&& Camera.PickByMouse(out SelectedObject))
139147
{
140-
if (PickByMouse(out SelectedObject))
141-
{
142-
TrackViewer.RenderProcess.Viewer.EditorShapes.SelectedObject = SelectedObject;
143-
FillSelectedObjectData();
144-
}
148+
SelectedObjectChanged();
149+
}
150+
if (UserInput.IsMouseMiddleButtonPressed && UserInput.ModifiersMaskShiftCtrlAlt(false, false, false))
151+
{
152+
Camera.StoreRotationOrigin(Viewer.TerrainPoint);
153+
Viewer.EditorShapes.CrosshairPositionUpdateEnabled = false;
154+
}
155+
if (UserInput.IsMouseMiddleButtonDown && UserInput.ModifiersMaskShiftCtrlAlt(false, false, false))
156+
{
157+
Camera.RotateByMouse();
158+
}
159+
else
160+
{
161+
Viewer.EditorShapes.CrosshairPositionUpdateEnabled = true;
162+
}
163+
if (UserInput.IsMouseMiddleButtonDown && UserInput.ModifiersMaskShiftCtrlAlt(true, false, false))
164+
{
165+
Camera.PanByMouse();
166+
}
167+
else
168+
{
169+
Camera.ZoomByMouseWheel(1);
145170
}
146-
//SetCameraLocationStatus(TrackViewer.RenderProcess?.Viewer?.Camera?.CameraWorldLocation ?? new WorldLocation());
147-
FillCursorPositionStatus((TrackViewer.RenderProcess?.Viewer?.Camera as ViewerCamera)?.CursorPoint ?? new Vector3());
171+
172+
if (UserInput.IsPressed(UserCommand.EditorUnselectAll))
173+
{
174+
SelectedObject = null;
175+
SelectedObjectChanged();
176+
}
177+
178+
SetCameraLocationStatus(TrackViewer.RenderProcess?.Viewer?.Camera?.CameraWorldLocation ?? new WorldLocation());
179+
//FillCursorPositionStatus(TrackViewer.RenderProcess?.Viewer?.TerrainPoint ?? new Vector3());
148180
}
149181

150182
public void EndDraw()
@@ -181,8 +213,6 @@ private void SetCameraLocationStatus(WorldLocation cameraLocation)
181213

182214
private void FillCursorPositionStatus(Vector3 cursorPosition)
183215
{
184-
//SceneWindow.tileXZ.Text = string.Format(System.Globalization.CultureInfo.CurrentCulture,
185-
// "{0,-7} {1,-7}", cameraLocation.TileX, cameraLocation.TileZ);
186216
SceneWindow.LocationX.Text = string.Format(CultureInfo.InvariantCulture, "{0,3:F3} ", cursorPosition.X);
187217
SceneWindow.LocationY.Text = string.Format(CultureInfo.InvariantCulture, "{0,3:F3} ", cursorPosition.Y);
188218
SceneWindow.LocationZ.Text = string.Format(CultureInfo.InvariantCulture, "{0,3:F3} ", -cursorPosition.Z);
@@ -211,100 +241,22 @@ public async Task SetCameraLocation()
211241
TrackViewer.RenderProcess.Viewer.ViewerCamera.SetLocation(mouseLocation);
212242
}
213243

214-
protected bool PickByMouse(out StaticShape pickedObjectOut)
244+
void SelectedObjectChanged()
215245
{
216-
var viewer = TrackViewer.RenderProcess.Viewer;
217-
218-
if (viewer == null)
219-
{
220-
pickedObjectOut = 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-
object pickedObject = null;
230-
var pickedDistance = float.MaxValue;
231-
var boundingBoxes = new Orts.Viewer3D.BoundingBox[1];
232-
foreach (var worldFile in viewer.World.Scenery.WorldFiles)
233-
{
234-
foreach (var checkedObject in worldFile.sceneryObjects)
235-
{
236-
checkObject(checkedObject, checkedObject.BoundingBox, checkedObject.Location);
237-
}
238-
foreach (var checkedObject in worldFile.forestList)
239-
{
240-
var min = new Vector3(-checkedObject.ForestArea.X / 2, -checkedObject.ForestArea.Y / 2, 0);
241-
var max = new Vector3(checkedObject.ForestArea.X / 2, checkedObject.ForestArea.Y / 2, 15);
242-
boundingBoxes[0] = new Orts.Viewer3D.BoundingBox(Matrix.Identity, Matrix.Identity, Vector3.Zero, 0, min, max);
243-
checkObject(checkedObject, boundingBoxes, checkedObject.Position);
244-
}
245-
}
246-
247-
void checkObject(object checkedObject, Orts.Viewer3D.BoundingBox[] checkedBoundingBox, WorldPosition checkedLocation)
248-
{
249-
if (checkedBoundingBox?.Length > 0)
250-
{
251-
foreach (var boundingBox in checkedBoundingBox)
252-
{
253-
// Locate relative to the camera
254-
var dTileX = checkedLocation.TileX - camera.TileX;
255-
var dTileZ = checkedLocation.TileZ - camera.TileZ;
256-
var xnaDTileTranslation = checkedLocation.XNAMatrix;
257-
xnaDTileTranslation.M41 += dTileX * 2048;
258-
xnaDTileTranslation.M43 -= dTileZ * 2048;
259-
xnaDTileTranslation = boundingBox.ComplexTransform * xnaDTileTranslation;
260-
261-
var min = Vector3.Transform(boundingBox.Min, xnaDTileTranslation);
262-
var max = Vector3.Transform(boundingBox.Max, xnaDTileTranslation);
263-
264-
var xnabb = new Microsoft.Xna.Framework.BoundingBox(min, max);
265-
checkDistance(checkedObject, pickRay.Intersects(xnabb));
266-
}
267-
}
268-
else
269-
{
270-
var radius = 10f;
271-
var boundingSphere = new BoundingSphere(camera.XnaLocation(checkedLocation.WorldLocation), radius);
272-
checkDistance(checkedObject, pickRay.Intersects(boundingSphere));
273-
}
274-
}
275-
276-
void checkDistance(object checkedObject, float? checkedDistance)
277-
{
278-
if (checkedDistance != null && checkedDistance < pickedDistance)
279-
{
280-
pickedDistance = checkedDistance.Value;
281-
pickedObject = checkedObject;
282-
}
283-
}
284-
285-
pickedObjectOut = pickedObject as StaticShape;
286-
287-
if (pickedObjectOut != null)
288-
{
289-
var ppp = pickedObjectOut;
290-
var sb = new StringBuilder();
291-
var aaa = TrackViewer.RenderProcess.Viewer.World.Scenery.WorldFiles.Where(w =>
292-
w.TileX == ppp.Location.TileX && w.TileZ == ppp.Location.TileZ).ToArray();
293-
var bbb = aaa[0].MstsWFile;
294-
bbb.Tr_Worldfile.Serialize(sb);
295-
var ccc = sb.ToString();
296-
}
297-
return pickedObjectOut != null;
298-
}
299-
300-
void FillSelectedObjectData()
301-
{
302-
SceneWindow.Filename.Text = SelectedObject != null ? System.IO.Path.GetFileName(SelectedObject.SharedShape.FilePath) : "";
303-
SceneWindow.TileX.Text = SelectedObject?.Location.TileX.ToString(CultureInfo.InvariantCulture).Replace(",", "");
304-
SceneWindow.TileZ.Text = SelectedObject?.Location.TileZ.ToString(CultureInfo.InvariantCulture).Replace(",", "");
305-
SceneWindow.PosX.Text = SelectedObject?.Location.Location.X.ToString("N3", CultureInfo.InvariantCulture).Replace(",", "");
306-
SceneWindow.PosY.Text = SelectedObject?.Location.Location.Y.ToString("N3", CultureInfo.InvariantCulture).Replace(",", "");
307-
SceneWindow.PosZ.Text = SelectedObject?.Location.Location.Z.ToString("N3", CultureInfo.InvariantCulture).Replace(",", "");
246+
Viewer.EditorShapes.SelectedObject = SelectedObject;
247+
248+
SelectedWorldObject = Viewer.World.Scenery.WorldFiles
249+
.SingleOrDefault(w => w.TileX == SelectedObject?.Location.TileX && w.TileZ == SelectedObject?.Location.TileZ)
250+
?.MstsWFile?.Tr_Worldfile
251+
?.SingleOrDefault(o => o.UID == SelectedObject?.Uid);
252+
253+
//SceneWindow.Filename.Text = SelectedObject != null ? System.IO.Path.GetFileName(SelectedObject.SharedShape.FilePath) : "";
254+
//SceneWindow.TileX.Text = SelectedObject?.Location.TileX.ToString(CultureInfo.InvariantCulture).Replace(",", "");
255+
//SceneWindow.TileZ.Text = SelectedObject?.Location.TileZ.ToString(CultureInfo.InvariantCulture).Replace(",", "");
256+
//SceneWindow.PosX.Text = SelectedObject?.Location.Location.X.ToString("N3", CultureInfo.InvariantCulture).Replace(",", "");
257+
//SceneWindow.PosY.Text = SelectedObject?.Location.Location.Y.ToString("N3", CultureInfo.InvariantCulture).Replace(",", "");
258+
//SceneWindow.PosZ.Text = SelectedObject?.Location.Location.Z.ToString("N3", CultureInfo.InvariantCulture).Replace(",", "");
259+
//SceneWindow.Uid.Text = SelectedObject.Uid.ToString(CultureInfo.InvariantCulture).Replace(",", "");
308260
var q = new Quaternion();
309261
if (SelectedObject?.Location.XNAMatrix.Decompose(out var _, out q, out var _) ?? false)
310262
{
@@ -317,7 +269,16 @@ void FillSelectedObjectData()
317269
{
318270
SceneWindow.RotY.Text = "";
319271
}
320-
SceneWindow.Uid.Text = SelectedObject.Uid.ToString(CultureInfo.InvariantCulture).Replace(",", "");
272+
273+
if (SelectedObject is StaticShape ppp)
274+
{
275+
var sb = new StringBuilder();
276+
var aaa = Viewer.World.Scenery.WorldFiles
277+
.SingleOrDefault(w => w.TileX == SelectedObject.Location.TileX && w.TileZ == SelectedObject.Location.TileZ)
278+
?.MstsWFile?.Tr_Worldfile;
279+
aaa.Serialize(sb);
280+
var ccc = sb.ToString();
281+
}
321282
}
322283

323284
}

Source/Contrib/TrackViewer/TrackViewer.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,13 +324,14 @@ private void DrawLoadingMessage(string message)
324324
/// <param name="gameTime">Provides a snapshot of timing values.</param>
325325
protected override void Update(GameTime gameTime)
326326
{
327-
SceneViewer?.Update(gameTime);
328-
329327
if (!this.IsTrackViewerWindowActive)
330328
{
331329
lostFocus = true;
332330
if (this.IsRenderWindowActive)
331+
{
333332
base.Update(gameTime);
333+
SceneViewer?.Update(gameTime);
334+
}
334335
return;
335336
}
336337

@@ -548,6 +549,8 @@ protected override void Update(GameTime gameTime)
548549
SetTitle();
549550

550551
RenderProcess.IsMouseVisible = true;
552+
553+
SceneViewer?.Update(gameTime);
551554
}
552555

553556
/// <summary>

Source/Contrib/TrackViewer/UserInterface/SceneWindow.xaml

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
44
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
55
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6-
xmlns:local="clr-namespace:ORTS.TrackViewer.UserInterface"
6+
xmlns:local="clr-namespace:ORTS.TrackViewer"
77
mc:Ignorable="d"
88
Title="Scene View" SizeToContent="WidthAndHeight">
99
<DockPanel LastChildFill="True">
@@ -114,47 +114,52 @@
114114
</StatusBar>
115115
<Border BorderThickness="2">
116116
<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>
117+
<StackPanel.DataContext>
118+
<local:SceneViewer/>
119+
</StackPanel.DataContext>
120+
<ItemsControl ItemsSource="{Binding SelectedWorldObject}">
121+
<TextBox FontWeight="Bold" Name="Filename" Text="{Binding SelectedWorldObject.FileName}"/>
122+
<DockPanel>
123+
<TextBlock Text="UID: " PreviewTextInput="UintValidationTextBox"/>
124+
<TextBlock Name="Uid" Text="{Binding SelectedWorldObject.UID}"/>
125+
</DockPanel>
126+
<Grid>
127+
<Grid.ColumnDefinitions>
128+
<ColumnDefinition Width="Auto"/>
129+
<ColumnDefinition Width="*"/>
130+
<ColumnDefinition Width="Auto"/>
131+
<ColumnDefinition Width="*"/>
132+
</Grid.ColumnDefinitions>
133+
<TextBlock Grid.Column="0" Text="Tile X: " />
134+
<TextBox Grid.Column="1" Name="TileX" PreviewTextInput="IntValidationTextBox" Text="{Binding SelectedObject.Location.TileX}" />
135+
<TextBlock Grid.Column="2" Text=" Z: " />
136+
<TextBox Grid.Column="3" Name="TileZ" PreviewTextInput="IntValidationTextBox" Text="{Binding SelectedObject.Location.TileZ}" />
137+
</Grid>
138+
<Grid>
139+
<Grid.RowDefinitions>
140+
<RowDefinition Height="Auto" />
141+
<RowDefinition Height="Auto" />
142+
<RowDefinition Height="Auto" />
143+
<RowDefinition Height="Auto" />
144+
</Grid.RowDefinitions>
145+
<Grid.ColumnDefinitions>
146+
<ColumnDefinition Width="Auto" />
147+
<ColumnDefinition Width="*" />
148+
<ColumnDefinition Width="*" />
149+
</Grid.ColumnDefinitions>
150+
<TextBlock Grid.Row="0" Grid.Column="1" Text="Position" HorizontalAlignment="Center"/>
151+
<TextBlock Grid.Row="0" Grid.Column="2" Text="Rotation" HorizontalAlignment="Center"/>
152+
<TextBlock Grid.Row="1" Text="X: "/>
153+
<TextBlock Grid.Row="2" Text="Y: "/>
154+
<TextBlock Grid.Row="3" Text="Z: "/>
155+
<TextBox Grid.Row="1" Grid.Column="1" x:Name="PosX" Text="{Binding SelectedObject.Location.Location.X, StringFormat=N3}" PreviewTextInput="FloatValidationTextBox"/>
156+
<TextBox Grid.Row="2" Grid.Column="1" x:Name="PosY" Text="{Binding SelectedObject.Location.Location.Y, StringFormat=N3}" PreviewTextInput="FloatValidationTextBox"/>
157+
<TextBox Grid.Row="3" Grid.Column="1" x:Name="PosZ" Text="{Binding SelectedObject.Location.Location.Z, StringFormat=N3}" PreviewTextInput="FloatValidationTextBox"/>
158+
<TextBox Grid.Row="1" Grid.Column="2" x:Name="RotX" PreviewTextInput="FloatValidationTextBox"/>
159+
<TextBox Grid.Row="2" Grid.Column="2" x:Name="RotY" PreviewTextInput="FloatValidationTextBox"/>
160+
<TextBox Grid.Row="3" Grid.Column="2" x:Name="RotZ" PreviewTextInput="FloatValidationTextBox"/>
161+
</Grid>
162+
</ItemsControl>
158163
</StackPanel>
159164
</Border>
160165
<Grid DockPanel.Dock="Bottom" x:Name="GraphicsHostElement" />

0 commit comments

Comments
 (0)