Skip to content

Commit 8f19fcc

Browse files
Merge pull request #950 from sweiland-openrails/ControlRectangle
Ctrl-F5 showing yellow rectangles where mouse left button is active
2 parents d75170a + a98ff62 commit 8f19fcc

File tree

6 files changed

+192
-1
lines changed

6 files changed

+192
-1
lines changed

Source/ORTS.Common/Input/UserCommand.cs

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,21 @@
1-
namespace ORTS.Common.Input
1+
// COPYRIGHT 2024 by the Open Rails project.
2+
//
3+
// This file is part of Open Rails.
4+
//
5+
// Open Rails is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// Open Rails is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU General Public License
16+
// along with Open Rails. If not, see <http://www.gnu.org/licenses/>.
17+
18+
namespace ORTS.Common.Input
219
{
320
/// <summary>
421
/// Specifies game commands.
@@ -49,6 +66,7 @@ public enum UserCommand
4966
[GetString("Display Compass Window")] DisplayCompassWindow,
5067
[GetString("Display Train List Window")] DisplayTrainListWindow,
5168
[GetString("Display EOT List Window")] DisplayEOTListWindow,
69+
[GetString("Display Control Rectangles")] DisplayControlRectangle,
5270

5371
[GetString("Debug Speed Up")] DebugSpeedUp,
5472
[GetString("Debug Speed Down")] DebugSpeedDown,

Source/ORTS.Settings/InputSettings.cs

+1
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ static void InitializeCommands(UserCommandInput[] Commands)
515515
Commands[(int)UserCommand.DisplayTrainOperationsWindow] = new UserCommandKeyInput(0x43);
516516
Commands[(int)UserCommand.DisplayTrainDpuWindow] = new UserCommandKeyInput(0x43, KeyModifiers.Shift);
517517
Commands[(int)UserCommand.DisplayEOTListWindow] = new UserCommandKeyInput(0x43, KeyModifiers.Control);
518+
Commands[(int)UserCommand.DisplayControlRectangle] = new UserCommandKeyInput(0x3F, KeyModifiers.Control);
518519

519520
Commands[(int)UserCommand.GameAutopilotMode] = new UserCommandKeyInput(0x1E, KeyModifiers.Alt);
520521
Commands[(int)UserCommand.GameChangeCab] = new UserCommandKeyInput(0x12, KeyModifiers.Control);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// COPYRIGHT 2024 by the Open Rails project.
2+
//
3+
// This file is part of Open Rails.
4+
//
5+
// Open Rails is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// Open Rails is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU General Public License
16+
// along with Open Rails. If not, see <http://www.gnu.org/licenses/>.
17+
18+
using System.Collections.Generic;
19+
using System.Linq;
20+
using Microsoft.Xna.Framework;
21+
using Microsoft.Xna.Framework.Graphics;
22+
using Orts.Simulation.RollingStocks;
23+
using Orts.Viewer3D.RollingStock;
24+
using SpriteBatch = Microsoft.Xna.Framework.Graphics.SpriteBatch;
25+
26+
namespace Orts.Viewer3D.Popups
27+
{
28+
public class ControlRectangle : Window
29+
{
30+
private readonly Texture2D Line;
31+
private int Thickness = 1;
32+
private readonly Color Color = Color.Yellow;
33+
private readonly Viewer Viewer;
34+
private bool CabViewFront;
35+
private bool IsOverRectangle = false;
36+
private class ListRect
37+
{
38+
public bool Front;
39+
public Rectangle CabRectangle;
40+
public string Name;
41+
}
42+
private List<ListRect> ListRectangles = new List<ListRect>();
43+
private ListRect ListRects;
44+
45+
public ControlRectangle(WindowManager owner, Viewer viewer) : base(owner)
46+
{
47+
Line = new Texture2D(Owner.Viewer.GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
48+
Line.SetData(new[] { Color });
49+
Viewer = viewer;
50+
}
51+
public override void Draw(SpriteBatch spriteBatch)
52+
{
53+
if (Viewer.Camera is CabCamera && (Viewer.PlayerLocomotiveViewer as MSTSLocomotiveViewer)._hasCabRenderer)
54+
{
55+
var cabRenderer = (Viewer.PlayerLocomotiveViewer as MSTSLocomotiveViewer)._CabRenderer;
56+
57+
var loco = Viewer.PlayerLocomotive as MSTSLocomotive;
58+
CabViewFront = !loco.UsingRearCab;
59+
60+
var itemsFrontCount = loco.CabViewList[(int)CabViewType.Front].CVFFile.CabViewControls.Count();
61+
var itemsRearCount = loco.CabViewList.Count > 1 ? loco.CabViewList[(int)CabViewType.Rear].CVFFile.CabViewControls.Count() : 0;
62+
63+
foreach (var controlRenderer in cabRenderer.ControlMap.Values.Skip(CabViewFront ? 0 : itemsFrontCount).Take(CabViewFront ? itemsFrontCount : itemsRearCount))
64+
{
65+
if ((Viewer.Camera as CabCamera).SideLocation == controlRenderer.Control.CabViewpoint && controlRenderer is ICabViewMouseControlRenderer mouseRenderer)
66+
{
67+
if (mouseRenderer.isMouseControl())
68+
{
69+
Rectangle rectangle = mouseRenderer.DestinationRectangleGet();
70+
int width = rectangle.Width;
71+
int height = rectangle.Height;
72+
73+
if (width > 0)
74+
{
75+
// do not know why rectangles with width and height = 0 are there
76+
ListRects = ListRectangles.FirstOrDefault(c => c.Name == mouseRenderer.GetControlName() && c.Front == CabViewFront);
77+
if (ListRects == null)
78+
{
79+
ListRectangles.Add(new ListRect
80+
{
81+
CabRectangle = rectangle,
82+
Front = CabViewFront,
83+
Name = mouseRenderer.GetControlName(),
84+
});
85+
}
86+
else
87+
{
88+
ListRects.CabRectangle = rectangle;
89+
}
90+
91+
Thickness = 1; // default
92+
if (mouseRenderer.IsMouseWithin())
93+
{
94+
ListRects = ListRectangles.FirstOrDefault(c => c.CabRectangle == rectangle && c.Front == CabViewFront);
95+
96+
if (ListRects != null && rectangle.Intersects(ListRects.CabRectangle) && ListRects.Name == mouseRenderer.GetControlName() && !IsOverRectangle)
97+
{
98+
Thickness = 3; // Highlights the currently selected rectangle
99+
IsOverRectangle = true;
100+
}
101+
}
102+
103+
DrawRectangle(spriteBatch, rectangle.X, rectangle.Y, width, height, Thickness, Color);
104+
}
105+
}
106+
}
107+
}
108+
IsOverRectangle = false;
109+
}
110+
}
111+
112+
private void DrawRectangle(SpriteBatch spriteBatch, int newX, int newY, int width, int height, int Thickness, Color Color)
113+
{ // top line
114+
DrawLine(spriteBatch, newX, newY, width, Thickness, 0, Color);
115+
// bottom line
116+
DrawLine(spriteBatch, newX, newY + height - Thickness, width, Thickness, 0, Color);
117+
// left line
118+
DrawLine(spriteBatch, newX + Thickness, newY, height, Thickness, 90, Color);
119+
// right line
120+
DrawLine(spriteBatch, newX + width, newY, height, Thickness, 90, Color);
121+
}
122+
123+
private void DrawLine(SpriteBatch spriteBatch, int X, int Y, int width, int height, int degrees, Color Color)
124+
{
125+
spriteBatch.Draw(
126+
Line,
127+
new Rectangle(X, Y, width, height),
128+
null,
129+
Color,
130+
ConvertToRadiansFromDegrees(degrees),
131+
new Vector2(0, 0),
132+
SpriteEffects.None, 0);
133+
}
134+
135+
private float ConvertToRadiansFromDegrees(int angle)
136+
{
137+
return (float)((System.Math.PI / 180) * angle);
138+
}
139+
}
140+
}

Source/RunActivity/Viewer3D/RollingStock/MSTSLocomotiveViewer.cs

+12
Original file line numberDiff line numberDiff line change
@@ -1700,6 +1700,8 @@ public interface ICabViewMouseControlRenderer
17001700
void HandleUserInput();
17011701
string GetControlName();
17021702
string ControlLabel { get; }
1703+
Rectangle DestinationRectangleGet();
1704+
bool isMouseControl();
17031705
}
17041706

17051707
/// <summary>
@@ -2856,6 +2858,16 @@ protected int PercentToIndex(float percent)
28562858

28572859
return index;
28582860
}
2861+
2862+
public Rectangle DestinationRectangleGet()
2863+
{
2864+
return DestinationRectangle;
2865+
}
2866+
2867+
public bool isMouseControl()
2868+
{
2869+
return ControlDiscrete.MouseControl;
2870+
}
28592871
}
28602872

28612873
/// <summary>

Source/RunActivity/Viewer3D/RollingStock/SubSystems/ETCS/DriverMachineInterface.cs

+17
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,15 @@ public override void Draw(GraphicsDevice graphicsDevice)
775775
ControlView.SpriteBatch.End();
776776
ControlView.SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.Default, null, Shader);
777777
}
778+
779+
public Rectangle DestinationRectangleGet()
780+
{
781+
return DrawPosition;
782+
}
783+
public bool isMouseControl()
784+
{
785+
return true;
786+
}
778787
}
779788
public class DriverMachineInterfaceRenderer : CabViewControlRenderer, ICabViewMouseControlRenderer
780789
{
@@ -863,5 +872,13 @@ public override void Draw(GraphicsDevice graphicsDevice)
863872
ControlView.SpriteBatch.End();
864873
ControlView.SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.Default, null, Shader);
865874
}
875+
public Rectangle DestinationRectangleGet()
876+
{
877+
return DrawPosition;
878+
}
879+
public bool isMouseControl()
880+
{
881+
return true;
882+
}
866883
}
867884
}

Source/RunActivity/Viewer3D/Viewer.cs

+3
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public class Viewer
103103
public TrainListWindow TrainListWindow { get; private set; } // for switching driven train
104104
public TTDetachWindow TTDetachWindow { get; private set; } // for detaching player train in timetable mode
105105
public EOTListWindow EOTListWindow { get; private set; } // to select EOT
106+
public ControlRectangle ControlRectangle { get; private set; } // to display the control rectangles
106107
private OutOfFocusWindow OutOfFocusWindow; // to show colored rectangle around the main window when not in focus
107108

108109
// Route Information
@@ -501,6 +502,7 @@ internal void Initialize()
501502
TrainListWindow = new TrainListWindow(WindowManager);
502503
TTDetachWindow = new TTDetachWindow(WindowManager);
503504
EOTListWindow = new EOTListWindow(WindowManager);
505+
ControlRectangle = new ControlRectangle(WindowManager, this);
504506
if (Settings.SuppressConfirmations < (int)ConfirmLevel.Error)
505507
// confirm level Error might be set to suppressed when taking a movie
506508
// do not show the out of focus red square in that case
@@ -999,6 +1001,7 @@ void HandleUserInput(ElapsedTime elapsedTime)
9991001
if (UserInput.IsPressed(UserCommand.DebugSignalling)) if (UserInput.IsDown(UserCommand.DisplayNextWindowTab)) SignallingDebugWindow.TabAction(); else SignallingDebugWindow.Visible = !SignallingDebugWindow.Visible;
10001002
if (UserInput.IsPressed(UserCommand.DisplayTrainListWindow)) TrainListWindow.Visible = !TrainListWindow.Visible;
10011003
if (UserInput.IsPressed(UserCommand.DisplayEOTListWindow)) EOTListWindow.Visible = !EOTListWindow.Visible;
1004+
if (UserInput.IsPressed(UserCommand.DisplayControlRectangle)) ControlRectangle.Visible = !ControlRectangle.Visible;
10021005

10031006

10041007
if (UserInput.IsPressed(UserCommand.GameChangeCab))

0 commit comments

Comments
 (0)