diff --git a/assets/Controls/Default.controls b/assets/Controls/Default.controls index 0c0d9e75f..db9d111d7 100644 --- a/assets/Controls/Default.controls +++ b/assets/Controls/Default.controls @@ -1,4 +1,4 @@ -; Current control configuration +; Current control configuration ; ============================= ; This file was automatically generated. Please modify only if you know what you're doing. ; Last updated 2026.01.16 @@ -79,6 +79,7 @@ CAMERA_ZOOM_OUT, keyboard, Keypad0, 0 CAMERA_POI_PREVIOUS, keyboard, Keypad1, 0 CAMERA_POI_NEXT, keyboard, Keypad7, 0 CAMERA_RESET, keyboard, Keypad5, 0 +CAMERA_GRAB_TOGGLE, mouse, 2, 0 CAMERA_RESTRICTION, keyboard, R, 2 TIMETABLE_TOGGLE, keyboard, T, 2 TIMETABLE_UP, keyboard, Up, 2 diff --git a/assets/Languages/en-US.xlf b/assets/Languages/en-US.xlf index d678c5016..fb67028e8 100755 --- a/assets/Languages/en-US.xlf +++ b/assets/Languages/en-US.xlf @@ -900,6 +900,30 @@ positive direction + + Mouse: + + + Button: + + + Mouse + + + Left Click + + + Middle Click + + + Right Click + + + Scroll Up + + + Scroll Down + invalid direction @@ -1216,6 +1240,9 @@ Transition duration (sec): + + Zoom Scroll Speed: + Detail of simulation @@ -1312,6 +1339,7 @@ Prefer custom timetable + Choose... @@ -2209,6 +2237,9 @@ Resets the camera view to default values + + Toggles camera grab (Mouse look) + Activates or deactivates interior view camera restriction diff --git a/assets/Languages/id-ID.xlf b/assets/Languages/id-ID.xlf index 92a6e9bda..3fe8b554b 100644 --- a/assets/Languages/id-ID.xlf +++ b/assets/Languages/id-ID.xlf @@ -1,4 +1,4 @@ - + @@ -1156,6 +1156,38 @@ positive direction arah positif + + Mouse: + Mouse: + + + Button: + Tombol: + + + Mouse + Mouse + + + Left Click + Klik Kiri + + + Middle Click + Klik Tengah + + + Right Click + Klik Kanan + + + Scroll Up + Scroll Atas + + + Scroll Down + Scroll Bawah + invalid direction arah tidak valid @@ -1483,6 +1515,26 @@ Miscellaneous Lainnya + + Camera options + Pengaturan kamera + + + Smooth interior transition + Transisi interior halus + + + Smooth exterior transition + Transisi eksterior halus + + + Transition duration (sec): + Durasi transisi (detik): + + + Zoom Scroll Speed: + Kecepatan Scroll Zoom: + Detail of simulation Detail simulasi @@ -1609,6 +1661,7 @@ Prefer custom timetable Buat sendiri + Choose... Pilih.... @@ -2772,6 +2825,10 @@ Resets the camera view to default values Reset kamera + + Toggles camera grab (Mouse look) + Aktifkan/nonaktifkan kontrol kamera dengan mouse + Activates or deactivates interior view camera restriction Aktifkan / matikan batasan kamera diff --git a/source/OpenBVE/Game/Menu/Menu.Controls.cs b/source/OpenBVE/Game/Menu/Menu.Controls.cs index 4777281e2..53b1e85dd 100644 --- a/source/OpenBVE/Game/Menu/Menu.Controls.cs +++ b/source/OpenBVE/Game/Menu/Menu.Controls.cs @@ -1,4 +1,4 @@ -using LibRender2.Primitives; +using LibRender2.Primitives; using OpenBveApi.Colors; using OpenBveApi.Hosts; using OpenBveApi.Interface; @@ -71,6 +71,19 @@ private static string GetControlDescription(int idx) case ControlMethod.Invalid: str = Translations.GetInterfaceString(HostApplication.OpenBve, new[] { "menu", "joystick_notavailable" }); break; + case ControlMethod.Mouse: + str = Translations.GetInterfaceString(HostApplication.OpenBve, new[] { "controls", "assignment_mouse" }) + " ["; + switch (loadedControl.Element) + { + case 0: str += Translations.GetInterfaceString(HostApplication.OpenBve, new[] { "controls", "assignment_mouse_left" }); break; + case 1: str += Translations.GetInterfaceString(HostApplication.OpenBve, new[] { "controls", "assignment_mouse_middle" }); break; + case 2: str += Translations.GetInterfaceString(HostApplication.OpenBve, new[] { "controls", "assignment_mouse_right" }); break; + case 3: str += Translations.GetInterfaceString(HostApplication.OpenBve, new[] { "controls", "assignment_mouse_scrollup" }); break; + case 4: str += Translations.GetInterfaceString(HostApplication.OpenBve, new[] { "controls", "assignment_mouse_scrolldown" }); break; + default: str += loadedControl.Element; break; + } + str += "]"; + break; } return str; diff --git a/source/OpenBVE/System/GameWindow.cs b/source/OpenBVE/System/GameWindow.cs index 8d89bd0f7..ca9dc9630 100644 --- a/source/OpenBVE/System/GameWindow.cs +++ b/source/OpenBVE/System/GameWindow.cs @@ -267,8 +267,8 @@ protected override void OnRenderFrame(FrameEventArgs e) MainLoop.UpdateControlRepeats(RealTimeElapsed); MainLoop.ProcessKeyboard(); - MainLoop.UpdateMouse(RealTimeElapsed); MainLoop.ProcessControls(TimeElapsed); + MainLoop.UpdateMouse(RealTimeElapsed); if (Program.Joysticks.AttachedJoysticks.TryGetTypedValue(AbstractRailDriver.Guid, out AbstractRailDriver railDriver)) { if (Interface.CurrentOptions.RailDriverMPH) diff --git a/source/OpenBVE/System/Input/Controls.cs b/source/OpenBVE/System/Input/Controls.cs index 1945c8a52..4f667140c 100644 --- a/source/OpenBVE/System/Input/Controls.cs +++ b/source/OpenBVE/System/Input/Controls.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -332,6 +332,20 @@ internal static void LoadControls(string FileOrNull, out Control[] Controls) } } + else if (Method == ControlMethod.Mouse & Terms.Length >= 3) + { + if (int.TryParse(Terms[2], out int CurrentButton)) + { + Controls[Length].Method = Method; + Controls[Length].Element = CurrentButton; + Controls[Length].Option = 0; + if (Terms.Length >= 4 && int.TryParse(Terms[3], NumberStyles.Integer, Culture, out int Option)) + { + Controls[Length].Option = Option; + } + Valid = true; + } + } if (!Valid) { diff --git a/source/OpenBVE/System/Input/ProcessControls.Analog.cs b/source/OpenBVE/System/Input/ProcessControls.Analog.cs index df0e8d523..c9b0b43df 100644 --- a/source/OpenBVE/System/Input/ProcessControls.Analog.cs +++ b/source/OpenBVE/System/Input/ProcessControls.Analog.cs @@ -1,4 +1,4 @@ -using System; +using System; using LibRender2.Cameras; using LibRender2.Overlays; using OpenBveApi.Interface; @@ -217,7 +217,12 @@ private static void ProcessAnalogControl(double TimeElapsed, ref Control Control case Translations.Command.CameraMoveRight: case Translations.Command.CameraMoveUp: case Translations.Command.CameraMoveDown: - Program.Renderer.Camera.Move(Control.Command, Control.AnalogState); + double moveFactor = Control.AnalogState; + if (Control.Method == ControlMethod.Mouse && Control.Element >= 3) + { + moveFactor *= Interface.CurrentOptions.ZoomScrollSpeed; + } + Program.Renderer.Camera.Move(Control.Command, moveFactor); break; case Translations.Command.CameraRotateLeft: case Translations.Command.CameraRotateRight: @@ -225,13 +230,23 @@ private static void ProcessAnalogControl(double TimeElapsed, ref Control Control case Translations.Command.CameraRotateDown: case Translations.Command.CameraRotateCCW: case Translations.Command.CameraRotateCW: - Program.Renderer.Camera.Rotate(Control.Command, Control.AnalogState); + double rotateFactor = Control.AnalogState; + if (Control.Method == ControlMethod.Mouse && Control.Element >= 3) + { + rotateFactor *= 10.0; // Boost scroll rotation + } + Program.Renderer.Camera.Rotate(Control.Command, rotateFactor); break; case Translations.Command.CameraZoomIn: // camera zoom in if (TimeElapsed > 0.0) { - Program.Renderer.Camera.AlignmentDirection.Zoom = -CameraProperties.ZoomTopSpeed * Control.AnalogState; + double factor = Control.AnalogState; + if (Control.Method == ControlMethod.Mouse && Control.Element >= 3) + { + factor *= Interface.CurrentOptions.ZoomScrollSpeed; + } + Program.Renderer.Camera.AlignmentDirection.Zoom = -CameraProperties.ZoomTopSpeed * factor; } break; @@ -239,7 +254,12 @@ private static void ProcessAnalogControl(double TimeElapsed, ref Control Control // camera zoom out if (TimeElapsed > 0.0) { - Program.Renderer.Camera.AlignmentDirection.Zoom = CameraProperties.ZoomTopSpeed * Control.AnalogState; + double factor = Control.AnalogState; + if (Control.Method == ControlMethod.Mouse && Control.Element >= 3) + { + factor *= Interface.CurrentOptions.ZoomScrollSpeed; + } + Program.Renderer.Camera.AlignmentDirection.Zoom = CameraProperties.ZoomTopSpeed * factor; } break; @@ -248,15 +268,20 @@ private static void ProcessAnalogControl(double TimeElapsed, ref Control Control if (TimeElapsed > 0.0) { const double scrollSpeed = 250.0; + double timetableFactor = Control.AnalogState; + if (Control.Method == ControlMethod.Mouse && Control.Element >= 3) + { + timetableFactor *= 5.0; + } switch (Program.Renderer.CurrentTimetable) { case DisplayedTimetable.Default: - Timetable.DefaultTimetablePosition += scrollSpeed * Control.AnalogState * TimeElapsed; + Timetable.DefaultTimetablePosition += scrollSpeed * timetableFactor * TimeElapsed; if (Timetable.DefaultTimetablePosition > 0.0) Timetable.DefaultTimetablePosition = 0.0; break; case DisplayedTimetable.Custom: - Timetable.CustomTimetablePosition += scrollSpeed * Control.AnalogState * TimeElapsed; + Timetable.CustomTimetablePosition += scrollSpeed * timetableFactor * TimeElapsed; if (Timetable.CustomTimetablePosition > 0.0) Timetable.CustomTimetablePosition = 0.0; break; @@ -269,10 +294,15 @@ private static void ProcessAnalogControl(double TimeElapsed, ref Control Control if (TimeElapsed > 0.0) { const double scrollSpeed = 250.0; + double timetableFactor = Control.AnalogState; + if (Control.Method == ControlMethod.Mouse && Control.Element >= 3) + { + timetableFactor *= 5.0; + } switch (Program.Renderer.CurrentTimetable) { case DisplayedTimetable.Default: - Timetable.DefaultTimetablePosition -= scrollSpeed * Control.AnalogState * TimeElapsed; + Timetable.DefaultTimetablePosition -= scrollSpeed * timetableFactor * TimeElapsed; double max; if (Timetable.DefaultTimetableTexture != null) { @@ -291,7 +321,7 @@ private static void ProcessAnalogControl(double TimeElapsed, ref Control Control break; case DisplayedTimetable.Custom: - Timetable.CustomTimetablePosition -= scrollSpeed * Control.AnalogState * TimeElapsed; + Timetable.CustomTimetablePosition -= scrollSpeed * timetableFactor * TimeElapsed; Texture texture = Timetable.CurrentCustomTimetableDaytimeTexture ?? Timetable.CurrentCustomTimetableNighttimeTexture; if (texture != null) { diff --git a/source/OpenBVE/System/Input/ProcessControls.Digital.cs b/source/OpenBVE/System/Input/ProcessControls.Digital.cs index 5a5b81855..50813140a 100644 --- a/source/OpenBVE/System/Input/ProcessControls.Digital.cs +++ b/source/OpenBVE/System/Input/ProcessControls.Digital.cs @@ -12,6 +12,7 @@ using OpenBveApi.Motor; using OpenBveApi.Routes; using OpenBveApi.Runtime; +using OpenTK.Input; using RouteManager2.MessageManager; using RouteManager2.SignalManager; using RouteManager2.Stations; @@ -573,6 +574,19 @@ private static void ProcessDigitalControl(double TimeElapsed, ref Control Contro break; } + break; + case Translations.Command.CameraGrabToggle: + if (Program.Renderer.CurrentInterface == InterfaceType.Normal) + { + MainLoop.MouseGrabEnabled = !MainLoop.MouseGrabEnabled; + if (MainLoop.MouseGrabEnabled) + { + Program.Renderer.GameWindow.CursorVisible = false; + System.Drawing.Point center = Program.Renderer.GameWindow.PointToScreen(new System.Drawing.Point(Program.Renderer.GameWindow.ClientRectangle.Width / 2, Program.Renderer.GameWindow.ClientRectangle.Height / 2)); + Mouse.SetPosition(center.X, center.Y); + } + MainLoop.MouseGrabIgnoreOnce = true; + } break; case Translations.Command.DeviceConstSpeed: // const speed @@ -941,6 +955,8 @@ private static void ProcessDigitalControl(double TimeElapsed, ref Control Contro break; case Translations.Command.MenuActivate: // menu + MainLoop.MouseGrabEnabled = false; + Program.Renderer.GameWindow.CursorVisible = true; Game.Menu.PushMenu(MenuType.Top); break; case Translations.Command.MiscPause: diff --git a/source/OpenBVE/System/MainLoop.cs b/source/OpenBVE/System/MainLoop.cs index 5bc384c7b..ba7ad8878 100644 --- a/source/OpenBVE/System/MainLoop.cs +++ b/source/OpenBVE/System/MainLoop.cs @@ -126,7 +126,10 @@ PROCESS EVENTS internal static MouseState currentMouseState, previousMouseState; internal static bool MouseGrabEnabled = false; + private static bool scrollUpPressed = false; + private static bool scrollDownPressed = false; internal static bool MouseGrabIgnoreOnce = false; + private static int lastMouseX, lastMouseY; internal static OpenBveApi.Math.Vector2 MouseGrabTarget = new OpenBveApi.Math.Vector2(0.0, 0.0); /// Called when a mouse button is pressed @@ -140,11 +143,7 @@ internal static void mouseDownEvent(object sender, MouseButtonEventArgs e) return; } timeSinceLastMouseEvent = 0; - if (e.Button == MouseButton.Right) - { - MouseGrabEnabled = !MouseGrabEnabled; - MouseGrabIgnoreOnce = true; - } + ProcessMouseControl((int)e.Button, true); if (e.Button == MouseButton.Left) { switch (Program.Renderer.CurrentInterface) @@ -172,6 +171,7 @@ internal static void mouseUpEvent(object sender, MouseButtonEventArgs e) return; } timeSinceLastMouseEvent = 0; + ProcessMouseControl((int)e.Button, false); if (e.Button == MouseButton.Left) { if (Program.Renderer.CurrentInterface == InterfaceType.Normal) @@ -210,6 +210,21 @@ internal static void mouseWheelEvent(object sender, MouseWheelEventArgs e) { Game.Menu.ProcessMouseScroll(e.Delta); } + if (e.Delta != 0) + { + int element = e.Delta > 0 ? 3 : 4; + // Accumulate scroll delta in AnalogState for smoother multi-scroll frames + for (int i = 0; i < Interface.CurrentControls.Length; i++) + { + if (Interface.CurrentControls[i].Method == ControlMethod.Mouse && Interface.CurrentControls[i].Element == element) + { + Interface.CurrentControls[i].AnalogState += 1.0; + Interface.CurrentControls[i].DigitalState = DigitalControlState.Pressed; + } + } + if (element == 3) scrollUpPressed = true; + if (element == 4) scrollDownPressed = true; + } } internal static void UpdateMouse(double TimeElapsed) @@ -221,15 +236,33 @@ internal static void UpdateMouse(double TimeElapsed) else { timeSinceLastMouseEvent = 0; //Always show the mouse in the menu + Program.Renderer.GameWindow.CursorVisible = true; + MainLoop.MouseGrabEnabled = false; } if (Interface.CurrentOptions.CursorHideDelay > 0 && timeSinceLastMouseEvent > Interface.CurrentOptions.CursorHideDelay) { Program.Renderer.GameWindow.CursorVisible = false; } - else + + if (scrollUpPressed) { - Program.Renderer.GameWindow.CursorVisible = true; + ProcessMouseControl(3, false); + scrollUpPressed = false; + } + if (scrollDownPressed) + { + ProcessMouseControl(4, false); + scrollDownPressed = false; + } + + if (MainLoop.MouseGrabEnabled) + { + Program.Renderer.GameWindow.CursorVisible = false; + } + else if (Interface.CurrentOptions.CursorHideDelay > 0 && timeSinceLastMouseEvent > Interface.CurrentOptions.CursorHideDelay) + { + Program.Renderer.GameWindow.CursorVisible = false; } if (MainLoop.MouseGrabEnabled) @@ -244,8 +277,10 @@ internal static void UpdateMouse(double TimeElapsed) factor = 3.0; } - Program.Renderer.Camera.AlignmentDirection.Yaw += factor * MouseGrabTarget.X; - Program.Renderer.Camera.AlignmentDirection.Pitch -= factor * MouseGrabTarget.Y; + double zoomFactor = Math.Exp(Program.Renderer.Camera.Alignment.Zoom); + Program.Renderer.Camera.Alignment.Yaw += factor * MouseGrabTarget.X * 0.001 * zoomFactor; + Program.Renderer.Camera.Alignment.Pitch -= factor * MouseGrabTarget.Y * 0.001 * zoomFactor; + Program.Renderer.UpdateViewingDistances(Program.CurrentRoute.CurrentBackground.BackgroundImageDistance); MouseGrabTarget = OpenBveApi.Math.Vector2.Null; } } @@ -312,17 +347,30 @@ internal static void ProcessKeyboard() } if (MouseGrabEnabled) { - previousMouseState = currentMouseState; - currentMouseState = Mouse.GetState(); - if (previousMouseState != currentMouseState) + int centerX = Program.Renderer.GameWindow.ClientRectangle.Width / 2; + int centerY = Program.Renderer.GameWindow.ClientRectangle.Height / 2; + System.Drawing.Point screenCenter = Program.Renderer.GameWindow.PointToScreen(new System.Drawing.Point(centerX, centerY)); + + if (MouseGrabIgnoreOnce) { - if (MouseGrabIgnoreOnce) - { - MouseGrabIgnoreOnce = false; - } - else if (MouseGrabEnabled) + MouseGrabIgnoreOnce = false; + MouseState state = Mouse.GetCursorState(); + lastMouseX = state.X; + lastMouseY = state.Y; + MouseGrabTarget = OpenBveApi.Math.Vector2.Null; + } + else + { + MouseState state = Mouse.GetCursorState(); + int curX = state.X; + int curY = state.Y; + MouseGrabTarget = new OpenBveApi.Math.Vector2(curX - lastMouseX, curY - lastMouseY); + lastMouseX = curX; + lastMouseY = curY; + if (Math.Abs(curX - screenCenter.X) > 400 || Math.Abs(curY - screenCenter.Y) > 400) { - MouseGrabTarget = new OpenBveApi.Math.Vector2(currentMouseState.X - previousMouseState.X, currentMouseState.Y - previousMouseState.Y); + Mouse.SetPosition(screenCenter.X, screenCenter.Y); + MouseGrabIgnoreOnce = true; } } } @@ -603,5 +651,24 @@ internal static void CheckForOpenGlError(string Location) { } } #endif + private static void ProcessMouseControl(int element, bool pressed) + { + for (int i = 0; i < Interface.CurrentControls.Length; i++) + { + if (Interface.CurrentControls[i].Method == ControlMethod.Mouse && Interface.CurrentControls[i].Element == element) + { + if (pressed) + { + Interface.CurrentControls[i].AnalogState = 1.0; + Interface.CurrentControls[i].DigitalState = DigitalControlState.Pressed; + } + else + { + Interface.CurrentControls[i].AnalogState = 0.0; + Interface.CurrentControls[i].DigitalState = DigitalControlState.Released; + } + } + } + } } } diff --git a/source/OpenBVE/System/Options.cs b/source/OpenBVE/System/Options.cs index 68dc8b0a9..4c78522bf 100644 --- a/source/OpenBVE/System/Options.cs +++ b/source/OpenBVE/System/Options.cs @@ -22,6 +22,8 @@ internal class Options : BaseOptions { /// The on disk folder in which user interface components are stored internal string UserInterfaceFolder; + /// The speed at which the mouse scroll zooms the camera + internal double ZoomScrollSpeed; /// The accelerated time factor (1x to 5x) internal int TimeAccelerationFactor; ///// The current type of motion blur @@ -129,6 +131,7 @@ internal Options() TransparencyMode = TransparencyMode.Quality; AnisotropicFilteringLevel = 0; AnisotropicFilteringMaximum = 0; + ZoomScrollSpeed = 30.0; AntiAliasingLevel = 0; ViewingDistance = 600; QuadTreeLeafSize = 60; @@ -355,6 +358,7 @@ public override void Save(string fileName) Builder.AppendLine("keyRepeatDelay = " + (1000.0 * KeyRepeatDelay).ToString("0", Culture)); Builder.AppendLine("keyRepeatInterval = " + (1000.0 * KeyRepeatInterval).ToString("0", Culture)); Builder.AppendLine("raildrivermph = " + (RailDriverMPH ? "true" : "false")); + Builder.AppendLine("zoomScrollSpeed = " + ZoomScrollSpeed.ToString(Culture)); Builder.AppendLine(); Builder.AppendLine("[sound]"); Builder.AppendLine("model = " + SoundModel); @@ -565,6 +569,11 @@ internal static void LoadOptions() CurrentOptions.KeyRepeatInterval = interval * 0.001; block.GetValue(OptionsKey.RailDriverMPH, out CurrentOptions.RailDriverMPH); block.GetValue(OptionsKey.CursorHideDelay, out CurrentOptions.CursorHideDelay); + block.TryGetValue(OptionsKey.ZoomScrollSpeed, ref CurrentOptions.ZoomScrollSpeed); + if (CurrentOptions.ZoomScrollSpeed <= 0.0 || CurrentOptions.ZoomScrollSpeed > 100.0) + { + CurrentOptions.ZoomScrollSpeed = 30.0; + } break; case OptionsSection.Sound: block.GetEnumValue(OptionsKey.Model, out CurrentOptions.SoundModel); diff --git a/source/OpenBVE/UserInterface/formMain.Controls.cs b/source/OpenBVE/UserInterface/formMain.Controls.cs index dc97128f6..26d9bd103 100644 --- a/source/OpenBVE/UserInterface/formMain.Controls.cs +++ b/source/OpenBVE/UserInterface/formMain.Controls.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Drawing; using System.Linq; using System.Windows.Forms; @@ -54,13 +54,18 @@ private void listviewControls_SelectedIndexChanged(object sender, EventArgs e) { case ControlMethod.RailDriver: radiobuttonJoystick.Checked = true; break; + case ControlMethod.Mouse: + radiobuttonMouse.Checked = true; + break; default: radiobuttonKeyboard.Checked = false; radiobuttonJoystick.Checked = false; + radiobuttonMouse.Checked = false; textboxJoystickGrab.Enabled = false; break; } panelKeyboard.Enabled = radiobuttonKeyboard.Checked; + panelKeyboard.Visible = radiobuttonKeyboard.Checked; if (radiobuttonKeyboard.Checked) { if (Translations.TranslatedKeys.ContainsKey(Interface.CurrentControls[i].Key)) @@ -72,13 +77,20 @@ private void listviewControls_SelectedIndexChanged(object sender, EventArgs e) { checkboxKeyboardAlt.Checked = (Interface.CurrentControls[i].Modifier & KeyboardModifier.Alt) != 0; } else if (radiobuttonJoystick.Checked) { labelJoystickAssignmentValue.Text = GetControlDetails(i); + } else if (radiobuttonMouse.Checked) { + comboboxMouseButton.SelectedIndex = Interface.CurrentControls[i].Element; } else { comboboxKeyboardKey.SelectedIndex = -1; checkboxKeyboardShift.Checked = false; checkboxKeyboardCtrl.Checked = false; checkboxKeyboardAlt.Checked = false; + comboboxMouseButton.SelectedIndex = -1; } panelJoystick.Enabled = radiobuttonJoystick.Checked; + panelJoystick.Visible = radiobuttonJoystick.Checked; + panelMouse.Enabled = radiobuttonMouse.Checked; + panelMouse.Visible = radiobuttonMouse.Checked; + textboxJoystickGrab.Visible = radiobuttonJoystick.Checked || radiobuttonKeyboard.Checked; // finalize Tag = null; } @@ -91,11 +103,13 @@ private void listviewControls_SelectedIndexChanged(object sender, EventArgs e) { comboboxCommand.SelectedIndex = -1; radiobuttonKeyboard.Checked = false; radiobuttonJoystick.Checked = false; + radiobuttonMouse.Checked = false; groupboxControl.Enabled = false; comboboxKeyboardKey.SelectedIndex = -1; checkboxKeyboardShift.Checked = false; checkboxKeyboardCtrl.Checked = false; checkboxKeyboardAlt.Checked = false; + comboboxMouseButton.SelectedIndex = -1; labelJoystickAssignmentValue.Text = ""; Tag = null; buttonControlRemove.Enabled = false; @@ -122,6 +136,9 @@ private void UpdateControlListElement(ListViewItem Item, int Index, bool ResizeC case ControlMethod.Joystick: Item.ImageKey = Info.Type == Translations.CommandType.AnalogHalf || Info.Type == Translations.CommandType.AnalogFull ? @"joystick" : @"gamepad"; break; + case ControlMethod.Mouse: + Item.ImageKey = @"mouse"; + break; default: Item.ImageKey = null; break; @@ -266,6 +283,18 @@ private string GetControlDetails(int Index) { } return t; } + if (Interface.CurrentControls[Index].Method == ControlMethod.Mouse) { + string t = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","assignment_mouse"}) + Separator; + switch (Interface.CurrentControls[Index].Element) { + case 0: t += Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","assignment_mouse_left"}); break; + case 1: t += Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","assignment_mouse_middle"}); break; + case 2: t += Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","assignment_mouse_right"}); break; + case 3: t += Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","assignment_mouse_scrollup"}); break; + case 4: t += Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","assignment_mouse_scrolldown"}); break; + default: t += "{" + Interface.CurrentControls[Index].Element.ToString(Culture) + "}"; break; + } + return t; + } return Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","assignment_invalid"}); } @@ -359,12 +388,34 @@ private void updownCommandOption_ValueChanged(object sender, EventArgs e) { // keyboard private void radiobuttonKeyboard_CheckedChanged(object sender, EventArgs e) { textboxJoystickGrab.Enabled = radiobuttonJoystick.Checked || radiobuttonKeyboard.Checked; + textboxJoystickGrab.Visible = radiobuttonJoystick.Checked || radiobuttonKeyboard.Checked; if (Tag == null & listviewControls.SelectedIndices.Count == 1) { int i = listviewControls.SelectedIndices[0]; Interface.CurrentControls[i].Method = ControlMethod.Keyboard; UpdateControlListElement(listviewControls.Items[i], i, true); } panelKeyboard.Enabled = radiobuttonKeyboard.Checked; + panelKeyboard.Visible = radiobuttonKeyboard.Checked; + } + + // mouse + private void radiobuttonMouse_CheckedChanged(object sender, EventArgs e) { + if (Tag == null & listviewControls.SelectedIndices.Count == 1) { + int i = listviewControls.SelectedIndices[0]; + Interface.CurrentControls[i].Method = ControlMethod.Mouse; + UpdateControlListElement(listviewControls.Items[i], i, true); + } + panelMouse.Enabled = radiobuttonMouse.Checked; + panelMouse.Visible = radiobuttonMouse.Checked; + textboxJoystickGrab.Visible = radiobuttonJoystick.Checked || radiobuttonKeyboard.Checked; + } + + private void comboboxMouseButton_SelectedIndexChanged(object sender, EventArgs e) { + if (Tag == null & listviewControls.SelectedIndices.Count == 1) { + int i = listviewControls.SelectedIndices[0]; + Interface.CurrentControls[i].Element = comboboxMouseButton.SelectedIndex; + UpdateControlListElement(listviewControls.Items[i], i, true); + } } // key @@ -426,6 +477,7 @@ private void radiobuttonJoystick_CheckedChanged(object sender, EventArgs e) { UpdateControlListElement(listviewControls.Items[i], i, true); } panelJoystick.Enabled = radiobuttonJoystick.Checked; + panelJoystick.Visible = radiobuttonJoystick.Checked; if (radiobuttonJoystick.Checked || radiobuttonKeyboard.Checked) { textboxJoystickGrab.Enabled = true; @@ -434,6 +486,7 @@ private void radiobuttonJoystick_CheckedChanged(object sender, EventArgs e) { { textboxJoystickGrab.Enabled = false; } + textboxJoystickGrab.Visible = radiobuttonJoystick.Checked || radiobuttonKeyboard.Checked; textboxJoystickGrab.Text = Translations.GetInterfaceString(HostApplication.OpenBve, radiobuttonJoystick.Checked ? new[] {"controls","selection_joystick_assignment_grab"} : new[] {"controls","selection_keyboard_assignment_grab"}); } diff --git a/source/OpenBVE/UserInterface/formMain.Designer.cs b/source/OpenBVE/UserInterface/formMain.Designer.cs index cf15c3aaa..c8d62d789 100644 --- a/source/OpenBVE/UserInterface/formMain.Designer.cs +++ b/source/OpenBVE/UserInterface/formMain.Designer.cs @@ -137,6 +137,8 @@ private void InitializeComponent() { this.trackbarTransparency = new System.Windows.Forms.TrackBar(); this.panelOptionsRight = new System.Windows.Forms.Panel(); this.groupBoxOther = new System.Windows.Forms.GroupBox(); + this.labelZoomScrollSpeed = new System.Windows.Forms.Label(); + this.updownZoomScrollSpeed = new System.Windows.Forms.NumericUpDown(); this.comboBoxTimeTableDisplayMode = new System.Windows.Forms.ComboBox(); this.labelTimeTableDisplayMode = new System.Windows.Forms.Label(); this.groupBoxRailDriver = new System.Windows.Forms.GroupBox(); @@ -336,6 +338,10 @@ private void InitializeComponent() { this.labelJoystickAssignmentValue = new System.Windows.Forms.Label(); this.radiobuttonJoystick = new System.Windows.Forms.RadioButton(); this.radiobuttonKeyboard = new System.Windows.Forms.RadioButton(); + this.radiobuttonMouse = new System.Windows.Forms.RadioButton(); + this.panelMouse = new System.Windows.Forms.Panel(); + this.labelMouseButton = new System.Windows.Forms.Label(); + this.comboboxMouseButton = new System.Windows.Forms.ComboBox(); this.panelInfo = new System.Windows.Forms.Panel(); this.linkLabelReportBug = new System.Windows.Forms.LinkLabel(); this.linkLabelCheckUpdates = new System.Windows.Forms.LinkLabel(); @@ -2089,11 +2095,43 @@ private void InitializeComponent() { this.groupBoxOther.ForeColor = System.Drawing.Color.Black; this.groupBoxOther.Location = new System.Drawing.Point(0, 347); this.groupBoxOther.Name = "groupBoxOther"; - this.groupBoxOther.Size = new System.Drawing.Size(316, 48); + this.groupBoxOther.Size = new System.Drawing.Size(316, 50); this.groupBoxOther.TabIndex = 19; this.groupBoxOther.TabStop = false; this.groupBoxOther.Text = "Other"; // + // labelZoomScrollSpeed + // + this.labelZoomScrollSpeed.Location = new System.Drawing.Point(8, 98); + this.labelZoomScrollSpeed.Name = "labelZoomScrollSpeed"; + this.labelZoomScrollSpeed.Size = new System.Drawing.Size(130, 18); + this.labelZoomScrollSpeed.TabIndex = 4; + this.labelZoomScrollSpeed.Text = "Zoom Scroll Speed:"; + this.labelZoomScrollSpeed.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // updownZoomScrollSpeed + // + this.updownZoomScrollSpeed.Location = new System.Drawing.Point(200, 96); + this.updownZoomScrollSpeed.Maximum = new decimal(new int[] { + 100, + 0, + 0, + 0}); + this.updownZoomScrollSpeed.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.updownZoomScrollSpeed.Name = "updownZoomScrollSpeed"; + this.updownZoomScrollSpeed.Size = new System.Drawing.Size(152, 20); + this.updownZoomScrollSpeed.TabIndex = 3; + this.updownZoomScrollSpeed.Value = new decimal(new int[] { + 30, + 0, + 0, + 0}); + this.updownZoomScrollSpeed.ValueChanged += new System.EventHandler(this.updownZoomScrollSpeed_ValueChanged); + // // comboBoxTimeTableDisplayMode // this.comboBoxTimeTableDisplayMode.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); @@ -2654,10 +2692,12 @@ private void InitializeComponent() { this.groupboxCamera.Controls.Add(this.checkboxCameraExteriorTransition); this.groupboxCamera.Controls.Add(this.labelCameraTransitionSpeed); this.groupboxCamera.Controls.Add(this.updownCameraTransitionSpeed); + this.groupboxCamera.Controls.Add(this.labelZoomScrollSpeed); + this.groupboxCamera.Controls.Add(this.updownZoomScrollSpeed); this.groupboxCamera.ForeColor = System.Drawing.Color.Black; this.groupboxCamera.Location = new System.Drawing.Point(330, 0); this.groupboxCamera.Name = "groupboxCamera"; - this.groupboxCamera.Size = new System.Drawing.Size(321, 120); + this.groupboxCamera.Size = new System.Drawing.Size(321, 150); this.groupboxCamera.TabIndex = 22; this.groupboxCamera.TabStop = false; this.groupboxCamera.Text = "Camera options"; @@ -4312,6 +4352,8 @@ private void InitializeComponent() { this.groupboxControl.Controls.Add(this.panelJoystick); this.groupboxControl.Controls.Add(this.radiobuttonJoystick); this.groupboxControl.Controls.Add(this.radiobuttonKeyboard); + this.groupboxControl.Controls.Add(this.radiobuttonMouse); + this.groupboxControl.Controls.Add(this.panelMouse); this.groupboxControl.Enabled = false; this.groupboxControl.ForeColor = System.Drawing.Color.Black; this.groupboxControl.Location = new System.Drawing.Point(8, 349); @@ -4408,22 +4450,22 @@ private void InitializeComponent() { this.comboboxCommand.FormattingEnabled = true; this.comboboxCommand.Location = new System.Drawing.Point(88, 21); this.comboboxCommand.Name = "comboboxCommand"; - this.comboboxCommand.Size = new System.Drawing.Size(587, 21); + this.comboboxCommand.Size = new System.Drawing.Size(400, 21); this.comboboxCommand.TabIndex = 1; this.comboboxCommand.SelectedIndexChanged += new System.EventHandler(this.comboboxCommand_SelectedIndexChanged); // // updownCommandOption // - this.updownCommandOption.Location = new System.Drawing.Point(583, 48); + this.updownCommandOption.Location = new System.Drawing.Point(615, 21); this.updownCommandOption.Name = "updownCommandOption"; - this.updownCommandOption.Size = new System.Drawing.Size(52, 20); + this.updownCommandOption.Size = new System.Drawing.Size(60, 20); this.updownCommandOption.TabIndex = 6; this.updownCommandOption.ValueChanged += new System.EventHandler(this.updownCommandOption_ValueChanged); // // labelCommandOption // this.labelCommandOption.AutoEllipsis = true; - this.labelCommandOption.Location = new System.Drawing.Point(463, 51); + this.labelCommandOption.Location = new System.Drawing.Point(490, 24); this.labelCommandOption.Name = "labelCommandOption"; this.labelCommandOption.Size = new System.Drawing.Size(120, 18); this.labelCommandOption.TabIndex = 7; @@ -4465,7 +4507,7 @@ private void InitializeComponent() { this.panelJoystick.Controls.Add(this.labelJoystickAssignmentCaption); this.panelJoystick.Controls.Add(this.labelJoystickAssignmentValue); this.panelJoystick.Enabled = false; - this.panelJoystick.Location = new System.Drawing.Point(264, 72); + this.panelJoystick.Location = new System.Drawing.Point(232, 72); this.panelJoystick.Name = "panelJoystick"; this.panelJoystick.Size = new System.Drawing.Size(235, 48); this.panelJoystick.TabIndex = 4; @@ -4491,7 +4533,7 @@ private void InitializeComponent() { // radiobuttonJoystick // this.radiobuttonJoystick.AutoSize = true; - this.radiobuttonJoystick.Location = new System.Drawing.Point(272, 48); + this.radiobuttonJoystick.Location = new System.Drawing.Point(232, 48); this.radiobuttonJoystick.Name = "radiobuttonJoystick"; this.radiobuttonJoystick.Size = new System.Drawing.Size(66, 17); this.radiobuttonJoystick.TabIndex = 3; @@ -4512,6 +4554,51 @@ private void InitializeComponent() { this.radiobuttonKeyboard.UseVisualStyleBackColor = true; this.radiobuttonKeyboard.CheckedChanged += new System.EventHandler(this.radiobuttonKeyboard_CheckedChanged); // + // radiobuttonMouse + // + this.radiobuttonMouse.AutoSize = true; + this.radiobuttonMouse.Location = new System.Drawing.Point(456, 48); + this.radiobuttonMouse.Name = "radiobuttonMouse"; + this.radiobuttonMouse.Size = new System.Drawing.Size(60, 17); + this.radiobuttonMouse.TabIndex = 11; + this.radiobuttonMouse.TabStop = true; + this.radiobuttonMouse.Text = "Mouse:"; + this.radiobuttonMouse.UseVisualStyleBackColor = true; + this.radiobuttonMouse.CheckedChanged += new System.EventHandler(this.radiobuttonMouse_CheckedChanged); + // + // panelMouse + // + this.panelMouse.Controls.Add(this.comboboxMouseButton); + this.panelMouse.Controls.Add(this.labelMouseButton); + this.panelMouse.Enabled = false; + this.panelMouse.Location = new System.Drawing.Point(8, 72); + this.panelMouse.Name = "panelMouse"; + this.panelMouse.Size = new System.Drawing.Size(192, 48); + this.panelMouse.TabIndex = 12; + this.panelMouse.Visible = false; + // + // labelMouseButton + // + this.labelMouseButton.AutoEllipsis = true; + this.labelMouseButton.Location = new System.Drawing.Point(0, 3); + this.labelMouseButton.Name = "labelMouseButton"; + this.labelMouseButton.Size = new System.Drawing.Size(60, 18); + this.labelMouseButton.TabIndex = 0; + this.labelMouseButton.Text = "Button:"; + this.labelMouseButton.TextAlign = System.Drawing.ContentAlignment.TopRight; + // + // comboboxMouseButton + // + this.comboboxMouseButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.comboboxMouseButton.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboboxMouseButton.FormattingEnabled = true; + this.comboboxMouseButton.Location = new System.Drawing.Point(64, 0); + this.comboboxMouseButton.Name = "comboboxMouseButton"; + this.comboboxMouseButton.Size = new System.Drawing.Size(104, 21); + this.comboboxMouseButton.TabIndex = 1; + this.comboboxMouseButton.SelectedIndexChanged += new System.EventHandler(this.comboboxMouseButton_SelectedIndexChanged); + // // panelInfo // this.panelInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); @@ -6695,6 +6782,10 @@ private void InitializeComponent() { private System.Windows.Forms.GroupBox groupboxControl; private System.Windows.Forms.RadioButton radiobuttonJoystick; private System.Windows.Forms.RadioButton radiobuttonKeyboard; + private System.Windows.Forms.RadioButton radiobuttonMouse; + private System.Windows.Forms.Panel panelMouse; + private System.Windows.Forms.Label labelMouseButton; + private System.Windows.Forms.ComboBox comboboxMouseButton; private System.Windows.Forms.Panel panelKeyboard; private System.Windows.Forms.ComboBox comboboxKeyboardKey; private System.Windows.Forms.Label labelKeyboardKey; @@ -6889,6 +6980,8 @@ private void InitializeComponent() { private System.Windows.Forms.Button SaveFileNameButton; private System.Windows.Forms.TextBox textBoxPackageFileName; private System.Windows.Forms.GroupBox groupBoxOther; + private System.Windows.Forms.Label labelZoomScrollSpeed; + private System.Windows.Forms.NumericUpDown updownZoomScrollSpeed; private System.Windows.Forms.ComboBox comboBoxTimeTableDisplayMode; private System.Windows.Forms.Label labelTimeTableDisplayMode; private System.Windows.Forms.Label labelSaveAs; diff --git a/source/OpenBVE/UserInterface/formMain.Options.cs b/source/OpenBVE/UserInterface/formMain.Options.cs index 068943f4e..2a39fec87 100644 --- a/source/OpenBVE/UserInterface/formMain.Options.cs +++ b/source/OpenBVE/UserInterface/formMain.Options.cs @@ -195,5 +195,10 @@ private void comboboxCursor_SelectedIndexChanged(object sender, EventArgs e) if (Tag != null) return; Cursors.SelectedCursor(comboboxCursor, pictureboxCursor); } + + private void updownZoomScrollSpeed_ValueChanged(object sender, EventArgs e) + { + Interface.CurrentOptions.ZoomScrollSpeed = (double)updownZoomScrollSpeed.Value; + } } } diff --git a/source/OpenBVE/UserInterface/formMain.cs b/source/OpenBVE/UserInterface/formMain.cs index e9c132ee2..704aa644f 100644 --- a/source/OpenBVE/UserInterface/formMain.cs +++ b/source/OpenBVE/UserInterface/formMain.cs @@ -525,6 +525,7 @@ private void formMain_Load(object sender, EventArgs e) checkboxCameraInteriorTransition.Checked = Interface.CurrentOptions.CameraInteriorTransition; checkboxCameraExteriorTransition.Checked = Interface.CurrentOptions.CameraExteriorTransition; updownCameraTransitionSpeed.Value = (decimal)Interface.CurrentOptions.CameraTransitionSpeed; + updownZoomScrollSpeed.Value = (decimal)Interface.CurrentOptions.ZoomScrollSpeed; ListInputDevicePlugins(); if (Program.CurrentHost.MonoRuntime) { @@ -779,6 +780,11 @@ private void ApplyLanguage() checkboxCameraInteriorTransition.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"options","camera_interior_transition"}); checkboxCameraExteriorTransition.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"options","camera_exterior_transition"}); labelCameraTransitionSpeed.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"options","camera_transition_duration"}); + labelZoomScrollSpeed.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] { "options", "camera_zoom_scroll_speed" }); + if (labelZoomScrollSpeed.Text == "camera_zoom_scroll_speed") + { + labelZoomScrollSpeed.Text = "Zoom Scroll Speed:"; + } checkboxToppling.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"options","misc_simulation_toppling"}); checkboxCollisions.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"options","misc_simulation_collisions"}); checkboxDerailments.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"options","misc_simulation_derailments"}); @@ -994,6 +1000,14 @@ private void ApplyLanguage() checkboxKeyboardAlt.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","selection_keyboard_modifiers_alt"}); radiobuttonJoystick.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","selection_joystick"}); + radiobuttonMouse.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","selection_mouse"}); + labelMouseButton.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","selection_mouse_button"}); + comboboxMouseButton.Items.Clear(); + comboboxMouseButton.Items.Add(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","assignment_mouse_left"})); + comboboxMouseButton.Items.Add(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","assignment_mouse_middle"})); + comboboxMouseButton.Items.Add(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","assignment_mouse_right"})); + comboboxMouseButton.Items.Add(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","assignment_mouse_scrollup"})); + comboboxMouseButton.Items.Add(Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","assignment_mouse_scrolldown"})); labelJoystickAssignmentCaption.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","selection_joystick_assignment"}); textboxJoystickGrab.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","selection_keyboard_assignment_grab"}); groupboxJoysticks.Text = Translations.GetInterfaceString(HostApplication.OpenBve, new[] {"controls","attached"}); diff --git a/source/OpenBveApi/Interface/Input/Commands.CommandInfo.cs b/source/OpenBveApi/Interface/Input/Commands.CommandInfo.cs index 1a997a56d..776b72ba6 100644 --- a/source/OpenBveApi/Interface/Input/Commands.CommandInfo.cs +++ b/source/OpenBveApi/Interface/Input/Commands.CommandInfo.cs @@ -238,6 +238,7 @@ public static CommandInfo TryGetInfo(this Dictionary comma { Command.CameraPOIPrevious, new CommandInfo(Command.CameraPOIPrevious, CommandType.Digital, "CAMERA_POI_PREVIOUS") }, { Command.CameraPOINext, new CommandInfo(Command.CameraPOINext, CommandType.Digital, "CAMERA_POI_NEXT") }, { Command.CameraReset, new CommandInfo(Command.CameraReset, CommandType.Digital, "CAMERA_RESET") }, + { Command.CameraGrabToggle, new CommandInfo(Command.CameraGrabToggle, CommandType.Digital, "CAMERA_GRAB_TOGGLE") }, { Command.CameraRestriction, new CommandInfo(Command.CameraRestriction, CommandType.Digital, "CAMERA_RESTRICTION") }, { Command.TimetableToggle, new CommandInfo(Command.TimetableToggle, CommandType.Digital, "TIMETABLE_TOGGLE") }, { Command.TimetableUp, new CommandInfo(Command.TimetableUp, CommandType.AnalogHalf, "TIMETABLE_UP") }, diff --git a/source/OpenBveApi/Interface/Input/Commands.cs b/source/OpenBveApi/Interface/Input/Commands.cs index 18c450ead..e738bf49b 100644 --- a/source/OpenBveApi/Interface/Input/Commands.cs +++ b/source/OpenBveApi/Interface/Input/Commands.cs @@ -120,6 +120,8 @@ public enum Command CameraPOINext, /// Reset the camera to pointing immediately forwards at track-level CameraReset, + /// Toggles camera grab (Mouse looking) + CameraGrabToggle, /// Toggle camera restriction mode CameraRestriction, /// Shows or hides the in-game timetable diff --git a/source/OpenBveApi/Interface/Input/Control.cs b/source/OpenBveApi/Interface/Input/Control.cs index bc045e331..bbd8a1d5a 100644 --- a/source/OpenBveApi/Interface/Input/Control.cs +++ b/source/OpenBveApi/Interface/Input/Control.cs @@ -1,4 +1,4 @@ -using System; +using System; using OpenBveApi.Input; namespace OpenBveApi.Interface @@ -58,6 +58,9 @@ public override string ToString() } s += ", " + Option; break; + case ControlMethod.Mouse: + s += Element + ", " + Option; + break; } return s; } diff --git a/source/OpenBveApi/Interface/Input/ControlMethod.cs b/source/OpenBveApi/Interface/Input/ControlMethod.cs index 79b2fe4a5..511cc2b5f 100644 --- a/source/OpenBveApi/Interface/Input/ControlMethod.cs +++ b/source/OpenBveApi/Interface/Input/ControlMethod.cs @@ -1,4 +1,4 @@ -namespace OpenBveApi.Interface +namespace OpenBveApi.Interface { /// The method by which a control is activated public enum ControlMethod @@ -14,6 +14,8 @@ public enum ControlMethod /// This control is activated using the Input Device Plugin InputDevicePlugin = 4, /// This control is activated using a touch element - Touch = 5 + Touch = 5, + /// This control is activated using a mouse button or wheel + Mouse = 6 } } diff --git a/source/OpenBveApi/Math/Vectors/Vector3.cs b/source/OpenBveApi/Math/Vectors/Vector3.cs index 09c77609f..a37d5453e 100644 --- a/source/OpenBveApi/Math/Vectors/Vector3.cs +++ b/source/OpenBveApi/Math/Vectors/Vector3.cs @@ -321,6 +321,10 @@ public static implicit operator Vector3f(Vector3 v) /// The multiplied vector public static Vector3 operator *(Vector3 v, Transformation t) { + if (t == null) + { + return v; + } v = t.X * v.X + t.Y * v.Y + t.Z * v.Z; return v; } @@ -497,6 +501,10 @@ public void Rotate(Orientation3 orientation) { /// The transformation public void Rotate(Transformation transformation) { + if (transformation == null) + { + return; + } double x = transformation.X.X * X + transformation.Y.X * Y + transformation.Z.X * Z; double y = transformation.X.Y * X + transformation.Y.Y * Y + transformation.Z.Y * Z; double z = transformation.X.Z * X + transformation.Y.Z * Y + transformation.Z.Z * Z; diff --git a/source/OpenBveApi/System/BaseOptions.OptionsKey.cs b/source/OpenBveApi/System/BaseOptions.OptionsKey.cs index d0952ff24..d50a1e9d0 100644 --- a/source/OpenBveApi/System/BaseOptions.OptionsKey.cs +++ b/source/OpenBveApi/System/BaseOptions.OptionsKey.cs @@ -80,6 +80,7 @@ public enum OptionsKey KeyRepeatInterval, RailDriverMPH, CursorHideDelay, + ZoomScrollSpeed, // Sound Model, Range, diff --git a/source/OpenBveApi/World/Transformations.cs b/source/OpenBveApi/World/Transformations.cs index 0f3a786d0..d8bbc0a76 100644 --- a/source/OpenBveApi/World/Transformations.cs +++ b/source/OpenBveApi/World/Transformations.cs @@ -1,4 +1,4 @@ -using OpenBveApi.Math; +using OpenBveApi.Math; namespace OpenBveApi.World { @@ -81,6 +81,10 @@ public Transformation(double Yaw, double Pitch, double Roll) /// public Transformation(Transformation Transformation, double Yaw, double Pitch, double Roll) { + if (Transformation == null) + { + Transformation = NullTransformation; + } X = new Vector3(Transformation.X); Y = new Vector3(Transformation.Y); Z = new Vector3(Transformation.Z); @@ -99,6 +103,14 @@ public Transformation(Transformation Transformation, double Yaw, double Pitch, d /// The transformation to apply second public Transformation(Transformation firstTransformation, Transformation secondTransformation) { + if (firstTransformation == null) + { + firstTransformation = NullTransformation; + } + if (secondTransformation == null) + { + secondTransformation = NullTransformation; + } X = new Vector3(firstTransformation.X); Y = new Vector3(firstTransformation.Y); Z = new Vector3(firstTransformation.Z); @@ -133,6 +145,10 @@ public Transformation(Vector3f direction, Vector3f up, Vector3f side) /// The transformation to convert public static explicit operator Matrix4D(Transformation t) { + if (t == null) + { + return Matrix4D.NoTransformation; + } // X, Y and Z represent the basis vector. // Arrange them in row-major to create a change-of-basis matrix. // And converting from the left-handed coordinate system to the right-handed coordinate system by reversing the Z axis.