<commit_before>﻿// KSP Easy Vessel Switch
// Author: <EMAIL>
// This software is distributed under Public domain license.

using HighlightingSystem;
using KSPDev.ConfigUtils;
using KSPDev.GUIUtils;
using KSPDev.LogUtils;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace EasyVesselSwitch {

/// <summary>Main mod's class that monitors use interactions.</summary>
[KSPAddon(KSPAddon.Startup.Flight, false /*once*/)]
[PersistentFieldsFile("EasyVesselSwitch/Plugins/PluginData/settings.cfg", "")]
sealed class Controller : MonoBehaviour {
  // ===== BEGIN of persistent fields section.
  [PersistentField("UI/switchModifier")]
  static KeyModifiers switchModifier = KeyModifiers.AnyAlt;
  [PersistentField("UI/switchMouseButton")]
  static Mouse.Buttons switchMouseButton = Mouse.Buttons.Left;
  [PersistentField("UI/targetVesselHighlightColor")]
  static Color targetVesselHighlightColor = Color.yellow;
  [PersistentField("UI/newVesselHighlightTimeout")]
  static float newVesselHighlightTimeout = 0.5f;

  [PersistentField("CameraStabilization/animationDuration")]
  static float cameraStabilizationAnimationDuration = 1f;
  [PersistentField("CameraStabilization/mode")]
  static CameraStabilization cameraStabilizationMode = CameraStabilization.KeepDistanceAndRotation;
  [PersistentField("CameraStabilization/maxVesselDistance")]
  static int maxVesselDistance = 100;  // Meters.
  [PersistentField("CameraStabilization/switchModeKey")]
  static KeyCode switchStabilizationModeKey = KeyCode.F7;

  [PersistentField("VesselInfo/fontSize")]
  static int vesselInfoFontSize = 10;
  [PersistentField("VesselInfo/backgroundColor")]
  static Color vesselInfoBackgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.5f);
  [PersistentField("VesselInfo/textColor")]
  static Color vesselInfoTextColor = Color.white;
  [PersistentField("VesselInfo/hintPadding")]
  static int vesselInfoHintPadding = 3;
  // ===== END of persistent fields section.

  // ===== BEGIN of localizable strings
  Message SwitchToMsg = "Switch to:";
  Message CurrentVesselMsg = "Currently selected:";
  Message<VesselType, string> VesselTitleMsg = "{0}: {1}";
  Message<string, string, int> KerbalTitleMsg = "{0} ({1}-{2})";
  Message<float> VesselMassMsg = "Total mass {0:0.###}t";
  Message<string, double> VesselResourceMsg = "{0}: {1:P0}";
  Message<string> SinglePartTitleMsg = "Part: {0}";
  Message<string> AssemblyTitleMsg = "Assembly: {0}";
  Message<double> KerbalEvaFuelMsg = "EVA propellant: {0:F3}";
  Message VesselIsControllable = "Is controllable: YES";
  Message VesselIsNotControllable = "Is controllable: NO";
  Message<CameraStabilization> CameraStabilizationModeChanged = "EVS stabilization: {0}";
  Message<float> DistantVesselTargeted = "Vessel is too distant: {0:N0}m";
  // ===== END of localizable strings

  /// <summary>A mode of camera stabilization.</summary>
  enum CameraStabilization {
    /// <summary>No stabilization. Allow dfeault KSP behavior.</summary>
    None = 0,
    /// <summary>Keep camera at the same position and move focus to the new vessel.</summary>
    KeepPosition = 1,
    /// <summary>Keep the same camera distance and rotation as was on the old vessel.</summary>
    KeepDistanceAndRotation = 2,
  }

  /// <summary>Vessel which is currently hovered.</summary>
  Vessel hoveredVessel;
  /// <summary>Tells if camera needs to be adjused.</summary>
  bool needCameraFix;
  /// <summary>Overaly window to show info about vessel under the mouse cursor.</summary>
  HintOverlay vesselInfoOverlay;
  /// <summary>Old vessel context.</summary>
  VesselInfo oldInfo;
  /// <summary>New vessel context.</summary>
  VesselInfo newInfo;

  /// <summary>Overridden from MonoBehavior.</summary>
  /// <remarks>Registers listeners, reads configuration and creates global UI objects.</remarks>
  void Awake() {
    GameEvents.onVesselSwitching.Add(OnVesselSwitch);
    GameEvents.onVesselChange.Add(OnVesselChange);
    ConfigAccessor.ReadFieldsInType(typeof(Controller), null);
    vesselInfoOverlay = new HintOverlay(
        vesselInfoFontSize, vesselInfoHintPadding, vesselInfoTextColor, vesselInfoBackgroundColor);
  }

  /// <summary>Overridden from MonoBehavior.</summary>
  void OnDestroy() {
    GameEvents.onVesselSwitching.Remove(OnVesselSwitch);
    GameEvents.onVesselChange.Remove(OnVesselChange);
  }

  /// <summary>Overridden from MonoBehavior.</summary>
  /// <remarks>Persents hovered vessel info.</remarks>
  void OnGUI() {
    if (hoveredVessel != null) {
      ShowHoveredVesselInfo();
    }
  }

  /// <summary>Overridden from MonoBehavior.</summary>
  /// <remarks>Tracks keys and mouse moveement.</remarks>
  void Update() {
    // Cancel any selection if game is paused or time warped. Block UI as well. 
    if (Mathf.Approximately(Time.timeScale, 0f) || Time.timeScale > 1f) {
      if (hoveredVessel != null) {
        SetHoveredVessel(null);
      }
      return;
    }

    // Handle stabilization mode switch. 
    if (Input.GetKeyDown(switchStabilizationModeKey)) {
      cameraStabilizationMode = cameraStabilizationMode == CameraStabilization.KeepPosition
          ? CameraStabilization.KeepDistanceAndRotation
          : CameraStabilization.KeepPosition;
      ScreenMessaging.ShowPriorityScreenMessage(
          CameraStabilizationModeChanged.Format(cameraStabilizationMode));
    }

    // Handle the switch.
    if (Mouse.HoveredPart && EventChecker.IsModifierCombinationPressed(switchModifier)) {
      SetHoveredVessel(Mouse.HoveredPart.vessel);
      if (Mouse.GetAllMouseButtonsDown() == switchMouseButton
          && hoveredVessel != null && hoveredVessel != FlightGlobals.ActiveVessel) {
        if (hoveredVessel.DiscoveryInfo.Level != DiscoveryLevels.Owned) {
          // Cannot switch to unowned vessel. Invoke standard "soft" switch to have error message
          // triggered.
          FlightGlobals.SetActiveVessel(hoveredVessel);
        } else {
          // Use forced version since "soft" switch blocks on many normal situations (e.g. "on
          // ladder" or "in atmosphere").
          var vesselToSelect = hoveredVessel;  // Save hovered vessel as it'll be reset on blur. 
          SetHoveredVessel(null);
          FlightGlobals.ForceSetActiveVessel(vesselToSelect);
        }
      }
    } else if (hoveredVessel != null) {
      SetHoveredVessel(null);  // Cancel highlight.
    }
  }

  /// <summary>GameEvents callback.</summary>
  /// <remarks>Detects vessel switch and remembers old camera settings if switching from the<commit_msg>Rotate thru all stabilization modes<commit_after>﻿// KSP Easy Vessel Switch
// Author: <EMAIL>
// This software is distributed under Public domain license.

using HighlightingSystem;
using KSPDev.ConfigUtils;
using KSPDev.GUIUtils;
using KSPDev.LogUtils;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace EasyVesselSwitch {

/// <summary>Main mod's class that monitors use interactions.</summary>
[KSPAddon(KSPAddon.Startup.Flight, false /*once*/)]
[PersistentFieldsFile("EasyVesselSwitch/Plugins/PluginData/settings.cfg", "")]
sealed class Controller : MonoBehaviour {
  // ===== BEGIN of persistent fields section.
  [PersistentField("UI/switchModifier")]
  static KeyModifiers switchModifier = KeyModifiers.AnyAlt;
  [PersistentField("UI/switchMouseButton")]
  static Mouse.Buttons switchMouseButton = Mouse.Buttons.Left;
  [PersistentField("UI/targetVesselHighlightColor")]
  static Color targetVesselHighlightColor = Color.yellow;
  [PersistentField("UI/newVesselHighlightTimeout")]
  static float newVesselHighlightTimeout = 0.5f;

  [PersistentField("CameraStabilization/animationDuration")]
  static float cameraStabilizationAnimationDuration = 1f;
  [PersistentField("CameraStabilization/mode")]
  static CameraStabilization cameraStabilizationMode = CameraStabilization.KeepDistanceAndRotation;
  [PersistentField("CameraStabilization/maxVesselDistance")]
  static int maxVesselDistance = 100;  // Meters.
  [PersistentField("CameraStabilization/switchModeKey")]
  static KeyCode switchStabilizationModeKey = KeyCode.F7;

  [PersistentField("VesselInfo/fontSize")]
  static int vesselInfoFontSize = 10;
  [PersistentField("VesselInfo/backgroundColor")]
  static Color vesselInfoBackgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.5f);
  [PersistentField("VesselInfo/textColor")]
  static Color vesselInfoTextColor = Color.white;
  [PersistentField("VesselInfo/hintPadding")]
  static int vesselInfoHintPadding = 3;
  // ===== END of persistent fields section.

  // ===== BEGIN of localizable strings
  Message SwitchToMsg = "Switch to:";
  Message CurrentVesselMsg = "Currently selected:";
  Message<VesselType, string> VesselTitleMsg = "{0}: {1}";
  Message<string, string, int> KerbalTitleMsg = "{0} ({1}-{2})";
  Message<float> VesselMassMsg = "Total mass {0:0.###}t";
  Message<string, double> VesselResourceMsg = "{0}: {1:P0}";
  Message<string> SinglePartTitleMsg = "Part: {0}";
  Message<string> AssemblyTitleMsg = "Assembly: {0}";
  Message<double> KerbalEvaFuelMsg = "EVA propellant: {0:F3}";
  Message VesselIsControllable = "Is controllable: YES";
  Message VesselIsNotControllable = "Is controllable: NO";
  Message<CameraStabilization> CameraStabilizationModeChanged = "EVS stabilization: {0}";
  Message<float> DistantVesselTargeted = "Vessel is too distant: {0:N0}m";
  // ===== END of localizable strings

  /// <summary>A mode of camera stabilization.</summary>
  enum CameraStabilization {
    /// <summary>No stabilization. Allow dfeault KSP behavior.</summary>
    None = 0,
    /// <summary>Keep camera at the same position and move focus to the new vessel.</summary>
    KeepPosition = 1,
    /// <summary>Keep the same camera distance and rotation as was on the old vessel.</summary>
    KeepDistanceAndRotation = 2,
  }

  /// <summary>Vessel which is currently hovered.</summary>
  Vessel hoveredVessel;
  /// <summary>Tells if camera needs to be adjused.</summary>
  bool needCameraFix;
  /// <summary>Overaly window to show info about vessel under the mouse cursor.</summary>
  HintOverlay vesselInfoOverlay;
  /// <summary>Old vessel context.</summary>
  VesselInfo oldInfo;
  /// <summary>New vessel context.</summary>
  VesselInfo newInfo;

  /// <summary>Overridden from MonoBehavior.</summary>
  /// <remarks>Registers listeners, reads configuration and creates global UI objects.</remarks>
  void Awake() {
    GameEvents.onVesselSwitching.Add(OnVesselSwitch);
    GameEvents.onVesselChange.Add(OnVesselChange);
    ConfigAccessor.ReadFieldsInType(typeof(Controller), null);
    vesselInfoOverlay = new HintOverlay(
        vesselInfoFontSize, vesselInfoHintPadding, vesselInfoTextColor, vesselInfoBackgroundColor);
  }

  /// <summary>Overridden from MonoBehavior.</summary>
  void OnDestroy() {
    GameEvents.onVesselSwitching.Remove(OnVesselSwitch);
    GameEvents.onVesselChange.Remove(OnVesselChange);
  }

  /// <summary>Overridden from MonoBehavior.</summary>
  /// <remarks>Persents hovered vessel info.</remarks>
  void OnGUI() {
    if (hoveredVessel != null) {
      ShowHoveredVesselInfo();
    }
  }

  /// <summary>Overridden from MonoBehavior.</summary>
  /// <remarks>Tracks keys and mouse moveement.</remarks>
  void Update() {
    // Cancel any selection if game is paused or time warped. Block UI as well. 
    if (Mathf.Approximately(Time.timeScale, 0f) || Time.timeScale > 1f) {
      if (hoveredVessel != null) {
        SetHoveredVessel(null);
      }
      return;
    }

    // Handle stabilization mode switch. 
    if (Input.GetKeyDown(switchStabilizationModeKey)) {
      if (cameraStabilizationMode == CameraStabilization.None) {
        cameraStabilizationMode = CameraStabilization.KeepPosition;
      } else if (cameraStabilizationMode == CameraStabilization.KeepPosition) {
        cameraStabilizationMode = CameraStabilization.KeepDistanceAndRotation;
      } else {
        cameraStabilizationMode = CameraStabilization.None;
      }
      ScreenMessaging.ShowPriorityScreenMessage(
          CameraStabilizationModeChanged.Format(cameraStabilizationMode));
    }

    // Handle the switch.
    if (Mouse.HoveredPart && EventChecker.IsModifierCombinationPressed(switchModifier)) {
      SetHoveredVessel(Mouse.HoveredPart.vessel);
      if (Mouse.GetAllMouseButtonsDown() == switchMouseButton
          && hoveredVessel != null && hoveredVessel != FlightGlobals.ActiveVessel) {
        if (hoveredVessel.DiscoveryInfo.Level != DiscoveryLevels.Owned) {
          // Cannot switch to unowned vessel. Invoke standard "soft" switch to have error message
          // triggered.
          FlightGlobals.SetActiveVessel(hoveredVessel);
        } else {
          // Use forced version since "soft" switch blocks on many normal situations (e.g. "on
          // ladder" or "in atmosphere").
          var vesselToSelect = hoveredVessel;  // Save hovered vessel as it'll be reset on blur. 
          SetHoveredVessel(null);
          FlightGlobals.ForceSetActiveVessel(vesselToSelect);
        }
      }
    } else if (hoveredVessel != null) {
      SetHoveredVessel(null);  // Cancel highlight.
    }
  }

  /// <summary>GameEvents callback.</summary>
  /// <remarks>Detects vessel switch and remembers old camera settings if switching from the
{'fraction_non_alphanumeric': 0.11071937589078089, 'fraction_numerical': 0.006001050183782162, 'mean_word_length': 4.1815001943256895, 'pattern_counts': {'":': 0, '<': 97, '<?xml version=': 0, '>': 99, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3057310', 'n_tokens_mistral': 4054, 'n_tokens_neox': 3863, 'n_words': 926}