Flight engineer menu follows button anchor and clamps within screen bounds.
Flight engineer menu follows button anchor and clamps within screen bounds.

 Binary files a/Assets/Plugins/KerbalEngineer.Unity.dll and b/Assets/Plugins/KerbalEngineer.Unity.dll differ
--- a/KerbalEngineer.Unity/Flight/FlightMenu.cs
+++ b/KerbalEngineer.Unity/Flight/FlightMenu.cs
@@ -23,6 +23,7 @@
     using UnityEngine.EventSystems;
     using UnityEngine.UI;
 
+    [RequireComponent(typeof(RectTransform))]
     public class FlightMenu : CanvasGroupFader, IPointerEnterHandler, IPointerExitHandler
     {
         [SerializeField]
@@ -44,6 +45,8 @@
         private float m_SlowFadeDuration = 1.0f;
 
         private IFlightAppLauncher m_FlightAppLauncher;
+
+        private RectTransform m_RectTransform;
 
         public void OnPointerEnter(PointerEventData eventData)
         {
@@ -114,6 +117,14 @@
             }
         }
 
+        protected override void Awake()
+        {
+            base.Awake();
+
+            // cache components
+            m_RectTransform = GetComponent<RectTransform>();
+        }
+
         protected virtual void Start()
         {
             // set starting alpha to zero and fade in
@@ -123,11 +134,20 @@
 
         protected virtual void Update()
         {
+            if (m_FlightAppLauncher == null)
+            {
+                return;
+            }
+
             // set toggle states to match the actual states
-            if (m_FlightAppLauncher != null)
-            {
-                SetToggle(m_ShowEngineerToggle, m_FlightAppLauncher.showEngineer);
-                SetToggle(m_ControlBarToggle, m_FlightAppLauncher.controlBar);
+            SetToggle(m_ShowEngineerToggle, m_FlightAppLauncher.showEngineer);
+            SetToggle(m_ControlBarToggle, m_FlightAppLauncher.controlBar);
+
+            // update anchor position
+            if (m_RectTransform != null)
+            {
+                m_RectTransform.position = m_FlightAppLauncher.GetAnchor();
+                m_FlightAppLauncher.ClampToScreen(m_RectTransform);
             }
         }
 

--- a/KerbalEngineer.Unity/Flight/IFlightAppLauncher.cs
+++ b/KerbalEngineer.Unity/Flight/IFlightAppLauncher.cs
@@ -19,6 +19,7 @@
 namespace KerbalEngineer.Unity.Flight
 {
     using System.Collections.Generic;
+    using UnityEngine;
 
     public interface IFlightAppLauncher
     {
@@ -28,6 +29,10 @@
 
         bool showEngineer { get; set; }
 
+        void ClampToScreen(RectTransform rectTransform);
+
+        Vector3 GetAnchor();
+
         IList<ISectionModule> GetCustomSections();
 
         IList<ISectionModule> GetStockSections();

--- a/KerbalEngineer/Flight/FlightAppLauncher.cs
+++ b/KerbalEngineer/Flight/FlightAppLauncher.cs
@@ -19,6 +19,7 @@
 namespace KerbalEngineer.Flight
 {
     using System.Collections.Generic;
+    using KSP.UI;
     using Sections;
     using Unity.Flight;
     using UnityEngine;
@@ -31,8 +32,6 @@
         private GameObject m_MenuObject;
         private GameObject m_MenuPrefab;
 
-        public IList<ISectionModule> GetCustomSections { get; }
-
         /// <summary>
         ///     Gets the current instance of the FlightAppLauncher object.
         /// </summary>
@@ -45,6 +44,14 @@
         }
 
         /// <summary>
+        ///     Clamps the given rect transform within the screen bounds.
+        /// </summary>
+        public void ClampToScreen(RectTransform rectTransform)
+        {
+            UIMasterController.ClampToScreen(rectTransform, Vector2.zero);
+        }
+
+        /// <summary>
         ///     Gets or sets the control bar's visibility.
         /// </summary>
         public bool controlBar
@@ -67,11 +74,17 @@
             }
         }
 
+        /// <summary>
+        ///     Gets a list of custom sections.
+        /// </summary>
         IList<ISectionModule> IFlightAppLauncher.GetCustomSections()
         {
             return new List<ISectionModule>(SectionLibrary.CustomSections.ToArray());
         }
 
+        /// <summary>
+        ///     Gets a list of stock sections.
+        /// </summary>
         public IList<ISectionModule> GetStockSections()
         {
             return new List<ISectionModule>(SectionLibrary.StockSections.ToArray());

 Binary files a/Output/KerbalEngineer/KerbalEngineer.Unity.dll and b/Output/KerbalEngineer/KerbalEngineer.Unity.dll differ
 Binary files a/Output/KerbalEngineer/KerbalEngineer.dll and b/Output/KerbalEngineer/KerbalEngineer.dll differ