@@ -16,29 +16,48 @@ namespace FlyByWireSASMode
1616 [ DefaultExecutionOrder ( 1 ) ] // our LateUpdate() need to run after VesselAutopilotUI.LateUpdate()
1717 internal class FlyByWireSASMode : MonoBehaviour
1818 {
19+ private const string TEX_PATH = "FlyByWireSASMode/textures" ;
20+ // singleton accessor
1921 internal static FlyByWireSASMode instance ;
2022
23+ // internal state
2124 private static bool init ;
25+
26+ // sprites
2227 private static Sprite flyByWireSprite ;
28+ private static Sprite flyByWirePlaneSprite ;
2329 private static Sprite parallelPosSprite ;
2430 private static Sprite parallelNegSprite ;
31+
32+ // config
2533 private static AutopilotMode requiredSASMode = AutopilotMode . Maneuver ;
26- private static float inputSensitivity = 1f ;
34+ internal static float inputSensitivity = 1f ;
2735
36+ // internal state
2837 private bool started ;
2938
39+ // SAS UI buttons references
3040 private UIStateToggleButton stabilityAssistButton ;
3141 private UIStateToggleButton flyByWireButton ;
42+ private UIStateToggleButton flyByWirePlaneButton ;
3243 private UIStateToggleButton parallelPosButton ;
3344 private UIStateToggleButton parallelNegButton ;
3445
46+ // stock navball reference
3547 internal NavBall navBall ;
48+
49+ // custom navball markers
3650 private GameObject navBallMarker ;
3751 private GameObject navBallArrow ;
3852
53+ // known active vessel (for polling purposes)
3954 private Vessel activeVessel ;
55+
56+ // per vessel direction and state tracking
4057 private VesselState activeVesselState ;
4158 private List < VesselState > nonActiveVesselStates = new List < VesselState > ( ) ;
59+
60+ // known state for polling based state change detection
4261 private bool isModeAvailableOnActiveVessel ;
4362
4463 private void Awake ( )
@@ -68,21 +87,22 @@ private void Awake()
6887 }
6988 }
7089
71- flyByWireSprite = LoadSprite ( "FlyByWireSASMode/FlyByWireMarker" ) ;
72- parallelPosSprite = LoadSprite ( "FlyByWireSASMode/ParallelPosMarker" ) ;
73- parallelNegSprite = LoadSprite ( "FlyByWireSASMode/ParallelNegMarker" ) ;
74- }
75-
76- private static Sprite LoadSprite ( string path )
77- {
78- Texture2D tex = GameDatabase . Instance . GetTexture ( path , false ) ;
90+ Texture2D tex = GameDatabase . Instance . GetTexture ( TEX_PATH , false ) ;
7991 if ( tex == null )
8092 {
81- Debug . LogError ( $ "[FlyByWireSASMode] Unable to get 'GameData/{ path } .png' texture, make sure the plugin is installed in the right folder.") ;
82- return null ;
93+ Debug . LogError ( $ "[FlyByWireSASMode] Unable to get 'GameData/{ TEX_PATH } .png' texture, make sure the plugin is installed in the right folder.") ;
94+ return ;
8395 }
8496
85- return Sprite . Create ( tex , new Rect ( 0f , 0f , tex . width , tex . height ) , new Vector2 ( 0.5f , 0.5f ) ) ;
97+ CreateSprite ( tex , 0f , 0f , 64f , 64f , out flyByWireSprite ) ;
98+ CreateSprite ( tex , 0f , 64f , 64f , 64f , out flyByWirePlaneSprite ) ;
99+ CreateSprite ( tex , 0f , 128f , 34f , 34f , out parallelNegSprite ) ;
100+ CreateSprite ( tex , 34f , 128f , 34f , 34f , out parallelPosSprite ) ;
101+ }
102+
103+ private static void CreateSprite ( Texture2D tex , float xOffset , float yOffset , float xSize , float ySize , out Sprite sprite )
104+ {
105+ sprite = Sprite . Create ( tex , new Rect ( xOffset , tex . height - yOffset - ySize , xSize , ySize ) , new Vector2 ( 0.5f , 0.5f ) ) ;
86106 }
87107
88108 private IEnumerator Start ( )
@@ -99,6 +119,7 @@ private IEnumerator Start()
99119 button . onClick . AddListener ( DeactivateFromUI ) ;
100120
101121 flyByWireButton = CopySASButton ( autopilotUI , AutopilotMode . Maneuver , "FlyByWire" , "Fly by wire" , 7f , 25f , flyByWireSprite , ActivateFlyByWireFromUI ) ;
122+ flyByWirePlaneButton = CopySASButton ( autopilotUI , AutopilotMode . StabilityAssist , "FlyByWirePlane" , "Fly by wire\n (plane mode)" , 7f , 25f , flyByWirePlaneSprite , ActivateFlyByWirePlaneFromUI ) ;
102123 parallelPosButton = CopySASButton ( autopilotUI , AutopilotMode . Target , "Parallel" , "Parallel" , 5f , - 25f , parallelPosSprite , ActivateParallelPosFromUI ) ;
103124 parallelNegButton = CopySASButton ( autopilotUI , AutopilotMode . AntiTarget , "AntiParallel" , "AntiParallel" , 5f , - 25f , parallelNegSprite , ActivateParallelNegFromUI ) ;
104125
@@ -168,6 +189,21 @@ private void ActivateFlyByWireFromUI()
168189 SetUIMode ( CustomSASMode . FlyByWire ) ;
169190 }
170191
192+ private void ActivateFlyByWirePlaneFromUI ( )
193+ {
194+ if ( activeVesselState != null )
195+ {
196+ activeVesselState . sasMode = CustomSASMode . FlyByWirePlaneMode ;
197+ activeVesselState . ResetDirection ( ) ;
198+ }
199+ else
200+ {
201+ activeVesselState = new VesselState ( FlightGlobals . ActiveVessel , CustomSASMode . FlyByWirePlaneMode ) ;
202+ }
203+
204+ SetUIMode ( CustomSASMode . FlyByWirePlaneMode ) ;
205+ }
206+
171207 private void ActivateParallelPosFromUI ( )
172208 {
173209 if ( activeVesselState != null )
@@ -204,12 +240,14 @@ private void SetUIMode(CustomSASMode mode)
204240 if ( mode == CustomSASMode . Stock )
205241 {
206242 flyByWireButton . SetState ( false ) ;
243+ flyByWirePlaneButton . SetState ( false ) ;
207244 parallelPosButton . SetState ( false ) ;
208245 parallelNegButton . SetState ( false ) ;
209246 }
210247 else
211248 {
212249 flyByWireButton . SetState ( mode == CustomSASMode . FlyByWire ) ;
250+ flyByWirePlaneButton . SetState ( mode == CustomSASMode . FlyByWirePlaneMode ) ;
213251 parallelPosButton . SetState ( mode == CustomSASMode . ParallelPos ) ;
214252 parallelNegButton . SetState ( mode == CustomSASMode . ParallelNeg ) ;
215253
@@ -265,6 +303,7 @@ private void LateUpdate()
265303 {
266304 isModeAvailableOnActiveVessel = isModeAvailable ;
267305 flyByWireButton . gameObject . SetActive ( isModeAvailable ) ;
306+ flyByWirePlaneButton . gameObject . SetActive ( isModeAvailable ) ;
268307 parallelPosButton . gameObject . SetActive ( isModeAvailable ) ;
269308 parallelNegButton . gameObject . SetActive ( isModeAvailable ) ;
270309 }
@@ -305,7 +344,7 @@ private void LateUpdate()
305344 // continously disable the stability assist button
306345 stabilityAssistButton . SetState ( false ) ;
307346
308- if ( activeVesselState . sasMode == CustomSASMode . FlyByWire )
347+ if ( activeVesselState . sasMode == CustomSASMode . FlyByWire || activeVesselState . sasMode == CustomSASMode . FlyByWirePlaneMode )
309348 {
310349 // set marker position on navball
311350 Vector3 markerLocalPos = navBall . attitudeGymbal * ( activeVesselState . direction * navBall . VectorUnitScale ) ;
0 commit comments